diff --git a/pom.xml b/pom.xml index e1b9eb1e5..301538bf9 100644 --- a/pom.xml +++ b/pom.xml @@ -24,9 +24,10 @@ yudao-module-mall yudao-module-erp yudao-module-crm - - yudao-module-iot + yudao-module-mes + + yudao-module-ai ${project.artifactId} diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index 3e4ca9ef3..436aeefde 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -11,7 +11,7 @@ Target Server Version : 80200 (8.2.0) File Encoding : 65001 - Date: 14/02/2026 16:02:08 + Date: 06/04/2026 19:09:55 */ SET NAMES utf8mb4; @@ -90,8 +90,9 @@ CREATE TABLE `infra_api_error_log` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 23367 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_create_time`(`create_time` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 23664 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -127,7 +128,8 @@ CREATE TABLE `infra_codegen_column` ( `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_table_id`(`table_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 2880 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; -- ---------------------------- @@ -192,7 +194,8 @@ CREATE TABLE `infra_config` ( `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_config_key`(`config_key` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 14 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '参数配置表'; -- ---------------------------- @@ -250,7 +253,7 @@ CREATE TABLE `infra_file` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2163 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 2167 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -308,7 +311,8 @@ CREATE TABLE `infra_file_content` ( `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_config_id_path`(`config_id` ASC, `path` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 286 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- @@ -383,7 +387,9 @@ CREATE TABLE `infra_job_log` ( `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_job_id`(`job_id` ASC) USING BTREE, + INDEX `idx_create_time`(`create_time` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 987 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '定时任务日志表'; -- ---------------------------- @@ -456,7 +462,7 @@ CREATE TABLE `system_dict_data` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 3054 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; +) ENGINE = InnoDB AUTO_INCREMENT = 3446 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; -- ---------------------------- -- Records of system_dict_data @@ -854,7 +860,6 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1566, 6, '诙谐', '6', 'ai_write_tone', 0, '', '', '', '1', '2024-07-07 15:52:15', '1', '2024-07-07 15:52:15', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1567, 7, '有趣', '7', 'ai_write_tone', 0, '', '', '', '1', '2024-07-07 15:52:24', '1', '2024-07-07 15:52:24', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1568, 8, '正式', '8', 'ai_write_tone', 0, '', '', '', '1', '2024-07-07 15:54:33', '1', '2024-07-07 15:54:33', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1569, 5, '段落', '5', 'ai_write_format', 0, '', '', '', '1', '2024-07-07 15:49:54', '1', '2024-07-07 15:49:54', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1570, 1, '自动', '1', 'ai_write_format', 0, '', '', '', '1', '2024-07-07 15:19:34', '1', '2024-07-07 15:19:34', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1571, 2, '电子邮件', '2', 'ai_write_format', 0, '', '', '', '1', '2024-07-07 15:19:50', '1', '2024-07-07 15:49:30', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1572, 3, '消息', '3', 'ai_write_format', 0, '', '', '', '1', '2024-07-07 15:20:01', '1', '2024-07-07 15:49:38', b'0'); @@ -867,7 +872,6 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1579, 1, '自动', '1', 'ai_write_length', 0, '', '', '', '1', '2024-07-07 15:48:34', '1', '2024-07-07 15:48:34', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1580, 2, '短', '2', 'ai_write_length', 0, '', '', '', '1', '2024-07-07 15:48:44', '1', '2024-07-07 15:48:44', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1581, 3, '中等', '3', 'ai_write_length', 0, '', '', '', '1', '2024-07-07 15:48:52', '1', '2024-07-07 15:48:52', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1582, 4, '长', '4', 'ai_write_length', 0, '', '', '', '1', '2024-07-07 15:49:03', '1', '2024-07-07 15:49:03', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1584, 1, '撰写', '1', 'ai_write_type', 0, '', '', '', '1', '2024-07-10 21:26:00', '1', '2024-07-10 21:26:00', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1585, 2, '回复', '2', 'ai_write_type', 0, '', '', '', '1', '2024-07-10 21:26:06', '1', '2024-07-10 21:26:06', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1586, 2, '腾讯云', 'TENCENT', 'system_sms_channel_code', 0, '', '', '', '1', '2024-07-22 22:23:16', '1', '2024-07-22 22:23:16', b'0'); @@ -918,7 +922,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2041, 12, '厘斯', 'cst', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:22', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2042, 13, '巴', 'bar', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:24', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2043, 14, '纳克每升', 'ppt', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:27', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2044, 15, '微克每升', 'ppb', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:31', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2044, 15, '十亿分之一', 'ppb', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2026-04-05 15:53:29', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2045, 16, '微西每厘米', 'uS/cm', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:34', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2046, 17, '牛顿每库仑', 'N/C', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:38', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2047, 18, '伏特每米', 'V/m', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:43', b'0'); @@ -926,7 +930,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2049, 20, '毫米汞柱', 'mmHg', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:48', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2050, 21, '血糖', 'mmol/L', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:37:54', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2051, 22, '毫米每秒', 'mm/s', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:38:02', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2052, 23, '转每分钟', 'turn/m', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:38:07', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2052, 23, '转每米', 'turn/m', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2026-04-05 15:53:29', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2053, 24, '次', 'count', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:38:09', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2054, 25, '档', 'gear', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:38:11', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2055, 26, '步', 'stepCount', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:38:13', b'0'); @@ -943,7 +947,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2067, 37, '吨每小时', 't/h', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2068, 38, '千卡每小时', 'KCL/h', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2069, 39, '升每秒', 'L/s', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2070, 40, '兆帕', 'Mpa', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2070, 40, '兆帕', 'MPa', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2026-04-05 15:53:29', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2071, 41, '立方米每小时', 'm³/h', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2072, 42, '千乏时', 'kvarh', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2073, 43, '微克每升', 'μg/L', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); @@ -991,7 +995,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2115, 85, '节', 'kn', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2116, 86, '千米每小时', 'km/h', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2117, 87, '米每秒', 'm/s', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2118, 88, '秒', '″', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2118, 88, '角秒', '″', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2026-04-05 15:53:29', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2119, 89, '分', '′', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2120, 90, '度', '°', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2121, 91, '弧度', 'rad', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); @@ -1010,7 +1014,7 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2134, 104, '开尔文', 'K', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2135, 105, '吨', 't', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2136, 106, '摄氏度', '°C', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); -INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2137, 107, '毫帕', 'mPa', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2137, 107, '毫帕', '1e-3Pa', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2026-04-05 15:53:29', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2138, 108, '百帕', 'hPa', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2139, 109, '千帕', 'kPa', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2140, 110, '帕斯卡', 'Pa', 'iot_thing_model_unit', 0, '', '', '', '1', '2024-12-13 11:08:41', '1', '2025-03-17 09:40:46', b'0'); @@ -1105,6 +1109,279 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3051, 1, 'Modbus TCP', '1', 'iot_modbus_frame_format', 0, 'default', '', 'MBAP 头部格式', '1', '2025-06-12 22:56:06', '1', '2025-06-12 22:56:06', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3052, 2, 'Modbus RTU', '2', 'iot_modbus_frame_format', 0, 'warning', '', 'CRC16 校验格式', '1', '2025-06-12 22:56:06', '1', '2025-06-12 22:56:06', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3053, 1, '云端轮询', '1', 'iot_modbus_mode', 0, 'primary', '', '网关主动轮询读取设备寄存器', '1', '2025-06-12 22:56:06', '1', '2025-06-12 22:56:06', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3054, 1, '企业客户', '1', 'mes_client_type', 0, 'primary', '', '', '1', '2026-02-15 14:38:25', '1', '2026-02-15 14:38:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3055, 2, '个人', '2', 'mes_client_type', 0, 'success', '', '', '1', '2026-02-15 14:38:25', '1', '2026-02-15 14:38:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3056, 1, '优质供应商', 'A', 'mes_vendor_level', 0, 'success', '', '', '1', '2026-02-15 15:59:15', '1', '2026-02-15 15:59:15', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3057, 2, '正常', 'B', 'mes_vendor_level', 0, 'primary', '', '', '1', '2026-02-15 15:59:15', '1', '2026-02-15 15:59:15', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3058, 3, '重点关注', 'C', 'mes_vendor_level', 0, 'warning', '', '', '1', '2026-02-15 15:59:15', '1', '2026-02-15 15:59:15', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3059, 4, '劣质供应商', 'D', 'mes_vendor_level', 0, 'danger', '', '', '1', '2026-02-15 15:59:15', '1', '2026-02-15 15:59:15', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3060, 5, '黑名单', 'E', 'mes_vendor_level', 0, 'info', '', '', '1', '2026-02-15 15:59:15', '1', '2026-02-15 15:59:15', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3061, 1, '假期', '2', 'mes_cal_holiday_type', 0, 'success', '', '', '1', '2026-02-16 07:35:58', '1', '2026-02-16 11:20:42', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3062, 2, '工作日', '1', 'mes_cal_holiday_type', 0, 'primary', '', '', '1', '2026-02-16 07:35:58', '1', '2026-02-16 11:20:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3063, 1, '在库', '1', 'mes_tm_tool_status', 0, 'success', '', '', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3064, 2, '领用中', '2', 'mes_tm_tool_status', 0, 'primary', '', '', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3065, 3, '维修中', '3', 'mes_tm_tool_status', 0, 'warning', '', '', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3066, 4, '报废', '4', 'mes_tm_tool_status', 0, 'danger', '', '', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3067, 1, '定期维护', '1', 'mes_tm_mainten_type', 0, 'primary', '', '', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3068, 2, '按使用次数维护', '2', 'mes_tm_mainten_type', 0, 'success', '', '', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3069, 1, '停机', '1', 'mes_dv_machinery_status', 0, 'success', '', '', '1', '2026-02-17 01:00:06', '1', '2026-02-17 03:28:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3070, 2, '生产中', '2', 'mes_dv_machinery_status', 0, 'info', '', '', '1', '2026-02-17 01:00:06', '1', '2026-02-17 03:28:33', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3071, 3, '维护中', '3', 'mes_dv_machinery_status', 0, 'danger', '', '', '1', '2026-02-17 01:00:06', '1', '2026-02-17 03:28:41', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3072, 1, '尺寸', 'SIZE', 'mes_indicator_type', 0, '', '', '', '1', '2026-02-17 02:18:18', '1', '2026-02-21 15:25:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3073, 2, '外观', 'APPEARANCE', 'mes_indicator_type', 0, '', '', '', '1', '2026-02-17 02:18:18', '1', '2026-02-21 15:25:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3074, 3, '重量', 'WEIGHT', 'mes_indicator_type', 0, '', '', '', '1', '2026-02-17 02:18:18', '1', '2026-02-21 15:25:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3075, 4, '性能', 'PERFORMANCE', 'mes_indicator_type', 0, '', '', '', '1', '2026-02-17 02:18:18', '1', '2026-02-21 15:25:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3076, 5, '成分', 'COMPONENT', 'mes_indicator_type', 0, '', '', '', '1', '2026-02-17 02:18:18', '1', '2026-02-21 15:25:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3077, 1, '致命缺陷', '1', 'mes_defect_level', 0, 'danger', '', '', '1', '2026-02-17 02:18:18', '1', '2026-02-21 12:21:12', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3078, 2, '严重缺陷', '2', 'mes_defect_level', 0, 'warning', '', '', '1', '2026-02-17 02:18:18', '1', '2026-02-21 12:21:15', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3079, 3, '轻微缺陷', '3', 'mes_defect_level', 0, 'info', '', '', '1', '2026-02-17 02:18:18', '1', '2026-02-21 12:21:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3080, 1, '单白班', '1', 'mes_cal_shift_type', 0, 'primary', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3081, 2, '两班倒', '2', 'mes_cal_shift_type', 0, 'success', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3082, 3, '三班倒', '3', 'mes_cal_shift_type', 0, 'warning', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3083, 1, '按季度', '1', 'mes_cal_shift_method', 0, '', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3084, 2, '按月', '2', 'mes_cal_shift_method', 0, '', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3085, 3, '按周', '3', 'mes_cal_shift_method', 0, '', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3086, 4, '按天', '4', 'mes_cal_shift_method', 0, '', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3089, 0, '草稿', '0', 'mes_cal_plan_status', 0, 'info', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3090, 1, '已确认', '1', 'mes_cal_plan_status', 0, 'success', '', '', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3100, 0, '草稿', '0', 'mes_pro_work_order_status', 0, 'info', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3101, 1, '已确认', '1', 'mes_pro_work_order_status', 0, 'primary', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3102, 2, '已完成', '2', 'mes_pro_work_order_status', 0, 'success', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3103, 3, '已取消', '3', 'mes_pro_work_order_status', 0, 'warning', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3104, 1, '客户订单', '1', 'mes_pro_work_order_source_type', 0, 'primary', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3105, 2, '库存备货', '2', 'mes_pro_work_order_source_type', 0, 'success', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3106, 1, '自行生产', '1', 'mes_pro_work_order_type', 0, 'primary', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3107, 2, '代工', '2', 'mes_pro_work_order_type', 0, 'warning', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3108, 3, '采购', '3', 'mes_pro_work_order_type', 0, 'info', '', '', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3121, 1, 'IQC(来料检验)', '1', 'mes_qc_type', 0, 'primary', '', '来料质量检验', '1', '2026-02-18 14:12:05', '1', '2026-02-18 14:12:05', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3122, 2, 'IPQC(过程检验)', '2', 'mes_qc_type', 0, 'warning', '', '生产制程质量检验', '1', '2026-02-18 14:12:05', '1', '2026-03-24 15:21:34', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3123, 3, 'OQC(出货检验)', '3', 'mes_qc_type', 0, 'success', '', '出货质量检验', '1', '2026-02-18 14:12:05', '1', '2026-02-18 14:12:05', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3124, 4, 'RQC(退料检验)', '4', 'mes_qc_type', 0, 'danger', '', '退货质量检验', '1', '2026-02-18 14:12:05', '1', '2026-03-24 15:22:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3125, 0, '开始-开始(SS)', '0', 'mes_pro_link_type', 0, 'default', '', '前序开始后,后序可以开始', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3126, 1, '结束-结束(FF)', '1', 'mes_pro_link_type', 0, 'default', '', '前序结束后,后序才能结束', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3127, 2, '开始-结束(SF)', '2', 'mes_pro_link_type', 0, 'default', '', '前序开始后,后序才能结束', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3128, 3, '结束-开始(FS)', '3', 'mes_pro_link_type', 0, 'default', '', '前序结束后,后序才能开始', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3129, 1, '分钟', 'MINUTE', 'mes_time_unit_type', 0, 'default', '', '', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3130, 2, '小时', 'HOUR', 'mes_time_unit_type', 0, 'default', '', '', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3131, 3, '天', 'DAY', 'mes_time_unit_type', 0, 'default', '', '', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3132, 0, '草稿', '0', 'mes_pro_task_status', 0, 'info', '', '', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3133, 1, '进行中', '1', 'mes_pro_task_status', 0, 'primary', '', '', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3134, 2, '暂停', '2', 'mes_pro_task_status', 0, 'warning', '', '', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3135, 3, '已完成', '3', 'mes_pro_task_status', 0, 'success', '', '', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3136, 4, '已取消', '4', 'mes_pro_task_status', 0, 'danger', '', '', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3137, 1, '设备点检', '1', 'mes_dv_subject_type', 0, 'info', '', '', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3138, 2, '设备保养', '2', 'mes_dv_subject_type', 0, 'success', '', '', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3139, 1, '待保养', '1', 'mes_mainten_record_status', 0, 'info', '', NULL, 'admin', '2026-02-20 02:59:55', '1', '2026-02-20 15:57:13', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3140, 2, '已完成', '2', 'mes_mainten_record_status', 0, 'success', '', NULL, 'admin', '2026-02-20 02:59:55', '1', '2026-02-20 15:57:10', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3141, 1, '正常', '1', 'mes_mainten_status', 0, 'success', '', NULL, 'admin', '2026-02-20 02:59:55', 'admin', '2026-02-20 02:59:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3142, 2, '异常', '0', 'mes_mainten_status', 0, 'danger', '', NULL, 'admin', '2026-02-20 02:59:55', 'admin', '2026-02-20 02:59:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3143, 1, '天', '1', 'mes_dv_cycle_type', 0, 'default', '', '', '1', '2026-02-20 07:11:43', '1', '2026-02-20 07:11:43', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3144, 2, '周', '2', 'mes_dv_cycle_type', 0, 'default', '', '', '1', '2026-02-20 07:11:43', '1', '2026-02-20 07:11:43', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3145, 3, '月', '3', 'mes_dv_cycle_type', 0, 'default', '', '', '1', '2026-02-20 07:11:43', '1', '2026-02-20 07:11:43', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3146, 4, '年', '4', 'mes_dv_cycle_type', 0, 'default', '', '', '1', '2026-02-20 07:11:43', '1', '2026-02-20 07:11:43', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3147, 0, '草稿', '0', 'mes_dv_check_plan_status', 0, 'info', '', '', '1', '2026-02-20 07:11:43', '1', '2026-02-20 07:11:43', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3148, 1, '已启用', '1', 'mes_dv_check_plan_status', 0, 'success', '', '', '1', '2026-02-20 07:11:43', '1', '2026-02-20 07:11:43', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3149, 1, '待点检', '10', 'mes_dv_check_record_status', 0, 'info', '', NULL, 'admin', '2026-02-20 09:46:19', 'admin', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3150, 2, '已完成', '20', 'mes_dv_check_record_status', 0, 'success', '', NULL, 'admin', '2026-02-20 09:46:19', 'admin', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3151, 1, '正常', '1', 'mes_dv_check_result', 0, 'success', '', NULL, 'admin', '2026-02-20 09:46:19', 'admin', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3152, 2, '异常', '2', 'mes_dv_check_result', 0, 'danger', '', NULL, 'admin', '2026-02-20 09:46:19', 'admin', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3157, 1, '修复成功', '1', 'mes_dv_repair_result', 0, 'success', '', '', '1', '2026-02-20 10:56:24', '1', '2026-02-20 10:56:24', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3158, 2, '报废', '2', 'mes_dv_repair_result', 0, 'danger', '', '', '1', '2026-02-20 10:56:24', '1', '2026-02-20 10:56:24', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3161, 1, '校验通过', '1', 'mes_qc_check_result', 0, 'success', '', '', '1', '2026-02-20 11:23:35', '1', '2026-02-20 16:15:54', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3162, 2, '校验不通过', '2', 'mes_qc_check_result', 0, 'danger', '', '', '1', '2026-02-20 11:23:35', '1', '2026-02-20 16:15:52', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3166, 0, '未处置', '0', 'mes_pro_andon_status', 0, 'danger', '', '', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3167, 1, '已处置', '1', 'mes_pro_andon_status', 0, 'success', '', '', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3168, 1, '一级', '1', 'mes_pro_andon_level', 0, 'danger', '', '', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3169, 2, '二级', '2', 'mes_pro_andon_level', 0, 'warning', '', '', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3170, 3, '三级', '3', 'mes_pro_andon_level', 0, 'info', '', '', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3171, 0, '草稿', '0', 'mes_pro_feedback_status', 0, 'info', '', '', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3172, 2, '审批中', '2', 'mes_pro_feedback_status', 0, 'primary', '', '', '1', '2026-02-21 00:50:32', '1', '2026-03-19 00:51:54', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3173, 3, '待检验', '3', 'mes_pro_feedback_status', 0, 'warning', '', '', '1', '2026-02-21 00:50:32', '1', '2026-03-19 00:51:54', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3174, 4, '已完成', '4', 'mes_pro_feedback_status', 0, 'success', '', '', '1', '2026-02-21 00:50:32', '1', '2026-03-19 00:51:54', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3176, 1, '自行报工', '1', 'mes_pro_feedback_type', 0, 'primary', '', '', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3177, 2, '统一报工', '2', 'mes_pro_feedback_type', 0, 'success', '', '', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3178, 1, 'PC', 'PC', 'mes_pro_feedback_channel', 0, 'primary', '', '', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3179, 2, 'APP', 'APP', 'mes_pro_feedback_channel', 0, 'success', '', '', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3180, 3, 'PDA', 'PDA', 'mes_pro_feedback_channel', 0, 'info', '', '', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3181, 1, '浮点', '1', 'mes_qc_result_type', 0, 'primary', '', '', '1', '2026-02-21 13:37:17', '1', '2026-02-21 13:37:17', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3182, 2, '整数', '2', 'mes_qc_result_type', 0, 'success', '', '', '1', '2026-02-21 13:37:17', '1', '2026-02-21 13:37:17', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3183, 3, '文本', '3', 'mes_qc_result_type', 0, 'info', '', '', '1', '2026-02-21 13:37:17', '1', '2026-02-21 13:37:17', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3184, 4, '字典', '4', 'mes_qc_result_type', 0, 'warning', '', '', '1', '2026-02-21 13:37:17', '1', '2026-02-21 13:37:17', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3185, 5, '文件', '5', 'mes_qc_result_type', 0, 'danger', '', '', '1', '2026-02-21 13:37:17', '1', '2026-02-21 13:37:17', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3186, 1, '生产退料', '1', 'mes_rqc_type', 0, 'default', '', '生产退料检验', '1', '2026-02-22 06:44:09', '1', '2026-02-22 06:44:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3187, 2, '销售退货', '2', 'mes_rqc_type', 0, 'default', '', '销售退货检验', '1', '2026-02-22 06:44:09', '1', '2026-02-22 06:44:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3188, 1, '自制工序检验', '1', 'mes_ipqc_type', 0, 'primary', '', '', '1', '2026-02-22 07:01:04', '1', '2026-02-22 07:01:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3189, 2, '首检', '2', 'mes_ipqc_type', 0, 'success', '', '', '1', '2026-02-22 07:01:04', '1', '2026-02-22 07:01:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3190, 3, '巡检', '3', 'mes_ipqc_type', 0, 'warning', '', '', '1', '2026-02-22 07:01:04', '1', '2026-02-22 07:01:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3191, 4, '自检', '4', 'mes_ipqc_type', 0, 'info', '', '', '1', '2026-02-22 07:01:04', '1', '2026-02-22 07:01:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3192, 5, '成品检验', '5', 'mes_ipqc_type', 0, 'danger', '', '', '1', '2026-02-22 07:01:04', '1', '2026-02-22 07:01:04', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3205, 0, '草稿', '0', 'mes_wm_arrival_notice_status', 0, 'info', '', '', '1', '2026-02-22 14:53:18', '1', '2026-02-22 14:53:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3206, 2, '待质检', '2', 'mes_wm_arrival_notice_status', 0, 'warning', '', '', '1', '2026-02-22 14:53:18', '1', '2026-02-26 05:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3207, 3, '待入库', '3', 'mes_wm_arrival_notice_status', 0, 'success', '', '', '1', '2026-02-22 14:53:18', '1', '2026-02-26 05:24:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3208, 4, '已完成', '4', 'mes_wm_arrival_notice_status', 0, 'primary', '', '', '1', '2026-02-22 14:53:18', '1', '2026-02-26 05:24:52', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3209, 0, '草稿', '0', 'mes_wm_item_receipt_status', 0, 'info', '', '', '1', '2026-02-22 14:54:05', '1', '2026-02-22 14:54:05', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3210, 1, '待上架', '2', 'mes_wm_item_receipt_status', 0, 'warning', '', '', '1', '2026-02-22 14:54:05', '1', '2026-02-26 08:03:35', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3211, 2, '待执行入库', '3', 'mes_wm_item_receipt_status', 0, 'success', '', '', '1', '2026-02-22 14:54:05', '1', '2026-02-26 08:03:31', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3212, 3, '已完成', '4', 'mes_wm_item_receipt_status', 0, 'primary', '', '', '1', '2026-02-22 14:54:05', '1', '2026-02-26 08:03:20', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3213, 4, '已取消', '5', 'mes_wm_item_receipt_status', 0, 'danger', '', '', '1', '2026-02-22 14:54:05', '1', '2026-02-26 08:03:24', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3214, 1, '草稿', '0', 'mes_order_status', 0, 'info', '', '', '1', '2026-02-23 21:16:03', '1', '2026-02-23 21:16:03', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3215, 2, '已确认', '1', 'mes_order_status', 0, 'primary', '', '', '1', '2026-02-23 21:16:03', '1', '2026-02-23 21:16:03', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3216, 3, '审批中', '2', 'mes_order_status', 0, 'warning', '', '', '1', '2026-02-23 21:16:03', '1', '2026-02-23 21:16:03', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3217, 4, '已审批', '3', 'mes_order_status', 0, 'success', '', '', '1', '2026-02-23 21:16:03', '1', '2026-02-23 21:16:03', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3218, 5, '已完成', '4', 'mes_order_status', 0, 'success', '', '', '1', '2026-02-23 21:16:03', '1', '2026-02-23 21:16:03', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3219, 6, '已取消', '5', 'mes_order_status', 0, 'danger', '', '', '1', '2026-02-23 21:16:03', '1', '2026-02-23 21:16:03', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3220, 1, '草稿', '0', 'mes_wm_issue_status', 0, 'info', '', '草稿状态,未完成', '1', '2026-02-26 15:54:25', '1', '2026-02-26 15:54:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3221, 2, '已完成', '4', 'mes_wm_issue_status', 0, 'success', '', '已完成出库', '1', '2026-02-26 15:54:25', '1', '2026-02-26 15:54:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3222, 1, '草稿', '0', 'mes_wm_product_issue_status', 0, 'info', '', '草稿状态,可编辑', '1', '2026-02-26 16:39:12', '1', '2026-03-23 13:18:02', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3223, 2, '待拣货', '2', 'mes_wm_product_issue_status', 0, 'warning', '', '审批中,可执行拣货', '1', '2026-02-26 16:39:12', '1', '2026-03-23 13:18:02', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3224, 3, '待执行领出', '3', 'mes_wm_product_issue_status', 0, 'primary', '', '已审批,拣货完成', '1', '2026-02-26 16:39:12', '1', '2026-03-23 13:18:02', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3225, 4, '已完成', '4', 'mes_wm_product_issue_status', 0, 'success', '', '已完成出库', '1', '2026-02-26 16:39:12', '1', '2026-03-23 13:18:02', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3226, 5, '已取消', '5', 'mes_wm_product_issue_status', 0, 'success', '', '已完成出库', '1', '2026-02-26 16:39:12', '1', '2026-03-23 13:18:02', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3232, 1, '草稿', '0', 'mes_wm_return_issue_status', 0, 'info', '', '草稿状态,可编辑', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:28:24', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3233, 2, '待检验', '1', 'mes_wm_return_issue_status', 0, 'default', '', '已确认,等待质检', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:28:28', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3234, 3, '待上架', '2', 'mes_wm_return_issue_status', 0, 'warning', '', '检验完成,等待仓库上架', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:28:31', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3235, 4, '待执行退料', '3', 'mes_wm_return_issue_status', 0, 'primary', '', '上架完成,等待执行退料操作', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:28:34', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3236, 5, '已完成', '4', 'mes_wm_return_issue_status', 0, 'success', '', '退料执行完成,库存已更新', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:28:37', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3237, 6, '已取消', '5', 'mes_wm_return_issue_status', 0, 'danger', '', '已取消', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:28:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3238, 1, '余料退料', '1', 'mes_wm_return_issue_type', 0, 'success', '', '余料退回,直接合格', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:27:47', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3239, 2, '不良退料', '2', 'mes_wm_return_issue_type', 0, 'danger', '', '不良品退回', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:27:49', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3240, 3, '其他退料', '3', 'mes_wm_return_issue_type', 0, 'info', '', '其他原因退料', '1', '2026-02-28 14:11:12', '1', '2026-02-28 14:27:55', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3241, 1, '待检', '0', 'mes_wm_quality_status', 0, 'warning', '', '待检状态', '1', '2026-02-28 15:00:53', '1', '2026-02-28 15:00:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3242, 2, '合格', '1', 'mes_wm_quality_status', 0, 'success', '', '合格状态', '1', '2026-02-28 15:00:53', '1', '2026-02-28 15:00:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3243, 3, '不合格', '2', 'mes_wm_quality_status', 0, 'danger', '', '不合格状态', '1', '2026-02-28 15:00:53', '1', '2026-02-28 15:00:53', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3244, 1, '草稿', '0', 'mes_wm_product_receipt_status', 0, 'info', '', '草稿状态', '1', '2026-03-01 06:03:07', '1', '2026-03-01 06:03:07', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3245, 2, '待上架', '2', 'mes_wm_product_receipt_status', 0, 'primary', '', '待上架', '1', '2026-03-01 06:03:07', '1', '2026-03-01 06:03:07', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3246, 3, '待执行入库', '3', 'mes_wm_product_receipt_status', 0, 'warning', '', '待执行入库', '1', '2026-03-01 06:03:07', '1', '2026-03-01 06:03:07', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3247, 4, '已完成', '4', 'mes_wm_product_receipt_status', 0, 'success', '', '已完成', '1', '2026-03-01 06:03:07', '1', '2026-03-01 06:03:07', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3248, 5, '已取消', '5', 'mes_wm_product_receipt_status', 0, 'danger', '', '已取消', '1', '2026-03-01 06:03:07', '1', '2026-03-01 06:03:07', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3252, 1, '草稿', '0', 'mes_wm_product_sales_status', 0, 'info', '', '草稿状态', '1', '2026-03-02 08:55:11', '1', '2026-03-02 08:55:11', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3253, 3, '待拣货', '2', 'mes_wm_product_sales_status', 0, 'warning', '', '待拣货状态', '1', '2026-03-02 08:55:11', '1', '2026-03-27 11:44:48', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3254, 4, '待出库', '3', 'mes_wm_product_sales_status', 0, 'primary', '', '待出库状态', '1', '2026-03-02 08:55:11', '1', '2026-03-27 11:44:48', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3255, 5, '已完成', '4', 'mes_wm_product_sales_status', 0, 'success', '', '已完成状态', '1', '2026-03-02 08:55:11', '1', '2026-03-27 11:44:48', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3256, 6, '已取消', '5', 'mes_wm_product_sales_status', 0, 'danger', '', '已取消状态', '1', '2026-03-02 08:55:11', '1', '2026-03-27 11:44:48', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3272, 1, '草稿', '0', 'mes_wm_misc_receipt_status', 0, 'info', '', '草稿状态', '1', '2026-03-03 07:33:41', '1', '2026-03-03 07:33:41', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3273, 2, '待执行入库', '3', 'mes_wm_misc_receipt_status', 0, 'primary', '', '待执行入库状态', '1', '2026-03-03 07:33:41', '1', '2026-03-03 07:37:34', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3274, 3, '已完成', '4', 'mes_wm_misc_receipt_status', 0, 'success', '', '已完成状态', '1', '2026-03-03 07:33:41', '1', '2026-03-03 07:33:41', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3275, 4, '已取消', '5', 'mes_wm_misc_receipt_status', 0, 'danger', '', '已取消状态', '1', '2026-03-03 07:33:41', '1', '2026-03-03 07:33:41', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3277, 1, '库存调整', '1', 'mes_wm_misc_receipt_type', 0, 'primary', '', '库存调整入库', '1', '2026-03-03 07:34:33', '1', '2026-03-03 07:34:33', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3278, 1, '库存调整', '1', 'mes_wm_misc_issue_type', 0, 'primary', '', '库存调整出库', '1', '2026-03-03 07:34:33', '1', '2026-03-03 07:34:33', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3279, 2, '报废出库', '2', 'mes_wm_misc_issue_type', 0, 'danger', '', '报废出库', '1', '2026-03-03 07:36:13', '1', '2026-03-03 07:36:13', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3280, 1, '草稿', '0', 'mes_wm_outsource_receipt_status', 0, 'info', '', '草稿状态', '1', '2026-03-03 14:03:57', '1', '2026-03-03 14:03:57', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3281, 2, '待检验', '1', 'mes_wm_outsource_receipt_status', 0, 'warning', '', '已确认,等待质检', '1', '2026-03-03 14:03:57', '1', '2026-03-03 14:03:57', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3282, 3, '待上架', '2', 'mes_wm_outsource_receipt_status', 0, 'primary', '', '检验完成,等待仓库上架', '1', '2026-03-03 14:03:57', '1', '2026-03-03 14:03:57', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3283, 4, '待执行入库', '3', 'mes_wm_outsource_receipt_status', 0, 'warning', '', '上架完成,等待执行入库操作', '1', '2026-03-03 14:03:57', '1', '2026-03-03 14:03:57', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3284, 5, '已完成', '4', 'mes_wm_outsource_receipt_status', 0, 'success', '', '入库执行完成,库存已更新', '1', '2026-03-03 14:03:57', '1', '2026-03-03 14:03:57', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3285, 6, '已取消', '5', 'mes_wm_outsource_receipt_status', 0, 'danger', '', '已取消', '1', '2026-03-03 14:03:57', '1', '2026-03-03 14:03:57', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3286, 1, '草稿', '0', 'mes_wm_outsource_issue_status', 0, 'info', '', '草稿状态,可编辑、删除、执行出库', '1', '2026-03-03 16:31:00', '1', '2026-03-03 16:31:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3287, 2, '待拣货', '2', 'mes_wm_outsource_issue_status', 0, 'warning', '', '待拣货状态', '1', '2026-03-03 16:31:00', '1', '2026-03-03 16:31:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3288, 3, '待执行出库', '3', 'mes_wm_outsource_issue_status', 0, 'primary', '', '待执行出库状态', '1', '2026-03-03 16:31:00', '1', '2026-03-03 16:31:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3289, 4, '已完成', '4', 'mes_wm_outsource_issue_status', 0, 'success', '', '已完成,库存已扣减', '1', '2026-03-03 16:31:00', '1', '2026-03-03 16:31:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3290, 5, '已取消', '5', 'mes_wm_outsource_issue_status', 0, 'danger', '', '已取消状态', '1', '2026-03-03 16:31:00', '1', '2026-03-03 16:31:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3301, 1, '输入字符', '1', 'mes_md_auto_code_part_type', 0, 'default', '', '输入字符', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3302, 2, '当前日期', '2', 'mes_md_auto_code_part_type', 0, 'primary', '', '当前日期时间', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3303, 3, '固定字符', '3', 'mes_md_auto_code_part_type', 0, 'success', '', '固定字符', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3304, 4, '流水号', '4', 'mes_md_auto_code_part_type', 0, 'warning', '', '流水号', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3305, 1, '左补齐', '1', 'mes_md_auto_code_padded_method', 0, 'primary', '', '左补齐', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3306, 2, '右补齐', '2', 'mes_md_auto_code_padded_method', 0, 'success', '', '右补齐', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3307, 1, '按年', '1', 'mes_md_auto_code_cycle_method', 0, 'default', '', '按年循环', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3308, 2, '按月', '2', 'mes_md_auto_code_cycle_method', 0, 'primary', '', '按月循环', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3309, 3, '按天', '3', 'mes_md_auto_code_cycle_method', 0, 'success', '', '按天循环', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3310, 4, '按小时', '4', 'mes_md_auto_code_cycle_method', 0, 'warning', '', '按小时循环', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3311, 5, '按分钟', '5', 'mes_md_auto_code_cycle_method', 0, 'danger', '', '按分钟循环', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3312, 10, '按传入字符', '10', 'mes_md_auto_code_cycle_method', 0, 'info', '', '按传入字符循环', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3313, 1, '二维码', '1', 'mes_wm_barcode_format', 0, 'primary', '', 'QR_CODE', '1', '2026-03-05 14:37:20', '1', '2026-03-06 13:18:21', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3314, 2, 'EAN13 商品条码', '2', 'mes_wm_barcode_format', 0, 'success', '', 'EAN13', '1', '2026-03-05 14:37:20', '1', '2026-03-06 13:18:23', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3315, 3, 'CODE39 工业条码', '3', 'mes_wm_barcode_format', 0, 'info', '', 'CODE39', '1', '2026-03-05 14:37:20', '1', '2026-03-06 13:18:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3316, 4, 'UPC-A 美国商品码', '4', 'mes_wm_barcode_format', 0, 'warning', '', 'UPC_A', '1', '2026-03-05 14:37:20', '1', '2026-03-06 13:18:28', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3318, 3, '库位', '104', 'mes_wm_barcode_biz_type', 0, 'default', '', 'AREA', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3319, 4, '装箱单', '105', 'mes_wm_barcode_biz_type', 0, 'default', '', 'PACKAGE', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3320, 5, '库存', '106', 'mes_wm_barcode_biz_type', 0, 'default', '', 'STOCK', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3321, 6, '批次', '107', 'mes_wm_barcode_biz_type', 0, 'default', '', 'BATCH', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3322, 7, '流转卡', '300', 'mes_wm_barcode_biz_type', 0, 'primary', '', 'PROCARD', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3323, 8, '工单', '301', 'mes_wm_barcode_biz_type', 0, 'primary', '', 'WORKORDER', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3324, 9, '流转单', '302', 'mes_wm_barcode_biz_type', 0, 'primary', '', 'TRANSORDER', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3325, 10, '设备', '400', 'mes_wm_barcode_biz_type', 0, 'success', '', 'MACHINERY', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3327, 12, '产品物料', '600', 'mes_wm_barcode_biz_type', 0, 'info', '', 'ITEM', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3328, 13, '供应商', '601', 'mes_wm_barcode_biz_type', 0, 'info', '', 'VENDOR', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3329, 14, '工作站', '602', 'mes_wm_barcode_biz_type', 0, 'info', '', 'WORKSTATION', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3330, 15, '车间', '603', 'mes_wm_barcode_biz_type', 0, 'info', '', 'WORKSHOP', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3331, 16, '人员', '604', 'mes_wm_barcode_biz_type', 0, 'info', '', 'USER', '1', '2026-03-05 14:37:20', '1', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3351, 1, '仓库', '102', 'mes_wm_barcode_biz_type', 0, '', '', NULL, '', '2026-03-07 06:22:27', '', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3352, 2, '库区', '103', 'mes_wm_barcode_biz_type', 0, '', '', NULL, '', '2026-03-07 06:22:27', '', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3353, 11, '工具', '500', 'mes_wm_barcode_biz_type', 0, '', '', NULL, '', '2026-03-07 06:22:27', '', '2026-03-07 06:22:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3354, 17, '客户', '605', 'mes_wm_barcode_biz_type', 0, '', '', NULL, '', '2026-03-07 06:22:27', '', '2026-03-07 06:25:19', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3355, 1, '草稿', '0', 'mes_wm_package_status', 0, 'info', '', '草稿状态,可编辑', '1', '2026-03-08 02:05:46', '1', '2026-03-08 02:05:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3356, 2, '已完成', '4', 'mes_wm_package_status', 0, 'success', '', '装箱已完成', '1', '2026-03-08 02:05:46', '1', '2026-03-08 02:05:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3357, 1, '草稿', '0', 'mes_wm_transfer_status', 0, 'info', '', '草稿状态,可编辑', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3358, 2, '待确认', '1', 'mes_wm_transfer_status', 0, 'warning', '', '外部调拨待确认到货', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3359, 3, '待上架', '2', 'mes_wm_transfer_status', 0, 'primary', '', '待维护目标库位明细', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3360, 4, '待执行', '3', 'mes_wm_transfer_status', 0, 'success', '', '目标库位已分配,待执行调拨', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3361, 5, '已完成', '4', 'mes_wm_transfer_status', 0, 'success', '', '调拨已完成', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3362, 6, '已取消', '5', 'mes_wm_transfer_status', 0, 'danger', '', '调拨已取消', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3363, 1, '内部调拨', '1', 'mes_wm_transfer_type', 0, 'success', '', '内部仓储调拨', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3364, 2, '外部调拨', '2', 'mes_wm_transfer_type', 0, 'warning', '', '外部配送/外部收货调拨', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3365, 1, '静态盘点', '1', 'mes_wm_stock_taking_type', 0, 'primary', '', '静态盘点', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3366, 2, '动态盘点', '2', 'mes_wm_stock_taking_type', 0, 'success', '', '动态盘点', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3367, 1, '仓库', '102', 'mes_wm_stock_taking_plan_param_type', 0, 'primary', '', '按仓库盘点', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3368, 2, '库区', '103', 'mes_wm_stock_taking_plan_param_type', 0, 'success', '', '按库区盘点', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3369, 3, '库位', '104', 'mes_wm_stock_taking_plan_param_type', 0, 'info', '', '按库位盘点', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3370, 4, '物料', '600', 'mes_wm_stock_taking_plan_param_type', 0, 'warning', '', '按物料盘点', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3371, 5, '批次', '107', 'mes_wm_stock_taking_plan_param_type', 0, 'danger', '', '按批次盘点', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3372, 1, '草稿', '0', 'mes_wm_stock_taking_task_status', 0, 'info', '', '草稿', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3373, 2, '审批中', '2', 'mes_wm_stock_taking_task_status', 0, 'primary', '', '盘点任务审批中', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3374, 3, '已完成', '4', 'mes_wm_stock_taking_task_status', 0, 'success', '', '已完成', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3375, 4, '已取消', '5', 'mes_wm_stock_taking_task_status', 0, 'danger', '', '已取消', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3377, 1, '正常', '1', 'mes_wm_stock_taking_task_line_status', 0, 'success', '', '正常', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3378, 2, '盘盈', '2', 'mes_wm_stock_taking_task_line_status', 0, 'primary', '', '盘盈', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3379, 3, '盘亏', '3', 'mes_wm_stock_taking_task_line_status', 0, 'danger', '', '盘亏', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3380, 6, '质量状态', '900', 'mes_wm_stock_taking_plan_param_type', 0, 'default', '', '按质量状态盘点', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3381, 1, '物料', 'ITEM', 'mes_md_item_or_product', 0, 'info', '', '', '1', '2026-03-15 01:55:06', '1', '2026-03-15 01:55:06', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3382, 2, '产品', 'PRODUCT', 'mes_md_item_or_product', 0, 'success', '', '', '1', '2026-03-15 01:55:06', '1', '2026-03-15 01:55:06', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3383, 1, '草稿', '0', 'mes_wm_item_consume_status', 0, 'info', '', '草稿状态', '1', '2026-03-19 15:06:23', '1', '2026-03-19 15:06:23', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3384, 2, '已完成', '4', 'mes_wm_item_consume_status', 0, 'success', '', '已完成', '1', '2026-03-19 15:06:23', '1', '2026-03-19 15:06:23', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3385, 1, '到货通知单', '100', 'mes_qc_source_doc_type', 0, 'primary', '', 'IQC', '1', '2026-03-26 13:01:09', '1', '2026-03-26 13:01:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3386, 2, '外协入库单', '121', 'mes_qc_source_doc_type', 0, 'warning', '', 'IQC', '1', '2026-03-26 13:01:09', '1', '2026-03-26 13:01:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3387, 3, '生产报工', '304', 'mes_qc_source_doc_type', 0, 'success', '', 'IPQC', '1', '2026-03-26 13:01:09', '1', '2026-03-26 13:01:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3388, 4, '销售出库单', '118', 'mes_qc_source_doc_type', 0, 'info', '', 'OQC', '1', '2026-03-26 13:01:09', '1', '2026-03-26 13:01:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3389, 5, '生产退料单', '116', 'mes_qc_source_doc_type', 0, 'danger', '', 'RQC', '1', '2026-03-26 13:01:09', '1', '2026-03-26 13:01:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3390, 6, '销售退货单', '119', 'mes_qc_source_doc_type', 0, 'default', '', 'RQC', '1', '2026-03-26 13:01:09', '1', '2026-03-26 13:01:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3397, 2, '待检测', '1', 'mes_wm_product_sales_status', 0, 'warning', '', 'OQC 检验中', '1', '2026-03-27 11:44:48', '1', '2026-03-27 11:44:48', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3398, 0, '草稿', '0', 'mes_wm_return_vendor_status', 0, 'info', '', NULL, '', '2026-03-29 13:49:57', '', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3399, 1, '待拣货', '2', 'mes_wm_return_vendor_status', 0, 'primary', '', NULL, '', '2026-03-29 13:49:57', '', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3400, 2, '待执行退货', '3', 'mes_wm_return_vendor_status', 0, 'warning', '', NULL, '', '2026-03-29 13:49:57', '', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3401, 3, '已完成', '4', 'mes_wm_return_vendor_status', 0, 'success', '', NULL, '', '2026-03-29 13:49:57', '', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3402, 4, '已取消', '5', 'mes_wm_return_vendor_status', 0, 'danger', '', NULL, '', '2026-03-29 13:49:57', '', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3403, 1, '草稿', '0', 'mes_wm_sales_notice_status', 0, 'info', '', '草稿状态,可以修改和删除', '1', '2026-03-30 08:54:30', '1', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3404, 2, '待出库', '3', 'mes_wm_sales_notice_status', 0, 'success', '', '已提交状态,不可修改和删除', '1', '2026-03-30 08:54:30', '1', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3405, 3, '已完成', '4', 'mes_wm_sales_notice_status', 0, '', '', NULL, '1', '2026-03-30 10:02:10', '1', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3406, 1, '草稿', '0', 'mes_wm_misc_issue_status', 0, 'info', '', '草稿状态', '1', '2026-03-30 15:00:18', '1', '2026-03-30 15:00:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3407, 2, '待出库', '3', 'mes_wm_misc_issue_status', 0, 'warning', '', '待出库状态', '1', '2026-03-30 15:00:18', '1', '2026-03-30 15:00:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3408, 3, '已完成', '4', 'mes_wm_misc_issue_status', 0, 'success', '', '执行出库后的状态', '1', '2026-03-30 15:00:18', '1', '2026-03-30 15:00:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3409, 4, '已取消', '5', 'mes_wm_misc_issue_status', 0, 'danger', '', '已取消状态', '1', '2026-03-30 15:00:18', '1', '2026-03-30 15:00:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3415, 1, '注塑', '1', 'mes_cal_calendar_type', 0, 'primary', '', '', '1', '2026-04-01 15:23:14', '1', '2026-04-01 16:08:31', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3416, 2, '机加工', '2', 'mes_cal_calendar_type', 0, 'success', '', '', '1', '2026-04-01 15:23:14', '1', '2026-04-01 16:08:32', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3417, 3, '组装', '3', 'mes_cal_calendar_type', 0, 'warning', '', '', '1', '2026-04-01 15:23:14', '1', '2026-04-01 16:08:33', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3418, 4, '仓库', '4', 'mes_cal_calendar_type', 0, 'danger', '', '', '1', '2026-04-01 15:23:14', '1', '2026-04-01 16:08:34', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3419, 0, '草稿', '0', 'mes_dv_repair_status', 0, 'info', '', '', '1', '2026-04-03 17:20:23', '1', '2026-04-03 17:20:23', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3420, 1, '维修中', '1', 'mes_dv_repair_status', 0, 'primary', '', '', '1', '2026-04-03 17:20:23', '1', '2026-04-03 17:20:23', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3421, 2, '待验收', '2', 'mes_dv_repair_status', 0, 'warning', '', '', '1', '2026-04-03 17:20:23', '1', '2026-04-03 17:20:23', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3422, 3, '已确认', '4', 'mes_dv_repair_status', 0, 'success', '', '', '1', '2026-04-03 17:20:23', '1', '2026-04-03 17:20:23', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3423, 0, '草稿', '0', 'mes_wm_return_sales_status', 0, 'info', '', '', '1', '2026-04-03 17:20:25', '1', '2026-04-03 17:20:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3424, 1, '待检验', '1', 'mes_wm_return_sales_status', 0, 'warning', '', '', '1', '2026-04-03 17:20:25', '1', '2026-04-03 17:20:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3425, 2, '待执行', '2', 'mes_wm_return_sales_status', 0, 'warning', '', '', '1', '2026-04-03 17:20:25', '1', '2026-04-03 17:20:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3426, 3, '待上架', '3', 'mes_wm_return_sales_status', 0, 'primary', '', '', '1', '2026-04-03 17:20:25', '1', '2026-04-03 17:20:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3427, 4, '已完成', '4', 'mes_wm_return_sales_status', 0, 'success', '', '', '1', '2026-04-03 17:20:25', '1', '2026-04-03 17:20:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3428, 5, '已取消', '5', 'mes_wm_return_sales_status', 0, 'danger', '', '', '1', '2026-04-03 17:20:25', '1', '2026-04-03 17:20:25', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3429, 1, '尺寸', 'SIZE', 'mes_defect_type', 0, '', '', '', '1', '2026-04-04 12:49:51', '1', '2026-04-04 12:49:51', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3430, 2, '外观', 'APPEARANCE', 'mes_defect_type', 0, '', '', '', '1', '2026-04-04 12:49:51', '1', '2026-04-04 12:49:51', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3431, 3, '重量', 'WEIGHT', 'mes_defect_type', 0, '', '', '', '1', '2026-04-04 12:49:51', '1', '2026-04-04 12:49:51', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3432, 4, '性能', 'PERFORMANCE', 'mes_defect_type', 0, '', '', '', '1', '2026-04-04 12:49:51', '1', '2026-04-04 12:49:51', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3433, 5, '成分', 'COMPONENT', 'mes_defect_type', 0, '', '', '', '1', '2026-04-04 12:49:51', '1', '2026-04-04 12:49:51', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3436, 1, '上工', '1', 'mes_pro_work_record_type', 0, 'success', '', '', '1', '2026-04-05 14:07:27', '1', '2026-04-05 14:07:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3437, 2, '下工', '2', 'mes_pro_work_record_type', 0, 'danger', '', '', '1', '2026-04-05 14:07:27', '1', '2026-04-05 14:07:27', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3443, 1, '草稿', '0', 'mes_wm_product_produce_status', 0, 'info', '', '草稿状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3444, 2, '已完成', '4', 'mes_wm_product_produce_status', 0, 'success', '', '已完成状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (3445, 3, '已取消', '5', 'mes_wm_product_produce_status', 0, 'danger', '', '已取消状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', b'0'); COMMIT; -- ---------------------------- @@ -1124,7 +1401,7 @@ CREATE TABLE `system_dict_type` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2012 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; +) ENGINE = InnoDB AUTO_INCREMENT = 2139 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; -- ---------------------------- -- Records of system_dict_type @@ -1233,6 +1510,7 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (1014, 'IoT 场景流转的触发类型枚举', 'iot_rule_scene_trigger_type_enum', 0, '', '1', '2025-03-20 14:59:44', '1', '2025-03-20 14:59:44', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (1015, 'IoT 设备消息类型枚举', 'iot_device_message_type_enum', 0, '', '1', '2025-03-20 15:01:15', '1', '2025-03-20 15:01:15', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (1016, 'IoT 规则场景的触发类型枚举', 'iot_rule_scene_action_type_enum', 0, '', '1', '2025-03-28 15:26:54', '1', '2025-03-28 15:29:13', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (1017, 'MES 物料消耗记录状态', 'mes_wm_item_consume_status', 0, 'MES 物料消耗记录状态', '1', '2026-03-19 15:06:23', '1', '2026-03-19 15:06:23', b'0', NULL); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2001, 'IoT 告警级别', 'iot_alert_level', 0, '', '1', '2025-06-27 20:30:57', '1', '2025-06-27 20:30:57', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2002, 'IoT 告警', 'iot_alert_receive_type', 0, '', '1', '2025-06-27 22:49:19', '1', '2025-06-27 22:49:19', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2003, 'IoT 固件设备范围', 'iot_ota_task_device_scope', 0, '', '1', '2025-07-02 09:42:49', '1', '2025-07-02 09:42:49', b'0', '1970-01-01 00:00:00'); @@ -1243,6 +1521,78 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2009, 'IoT 序列化类型', 'iot_serialize_type', 0, 'IoT 设备消息序列化类型', '1', '2026-02-04 00:33:16', '1', '2026-02-04 00:33:16', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2010, 'IoT Modbus 工作模式', 'iot_modbus_mode', 0, 'Modbus 设备数据采集模式', '1', '2025-06-12 22:55:46', '1', '2025-06-12 22:55:46', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2011, 'IoT Modbus 帧格式', 'iot_modbus_frame_format', 0, 'Modbus 数据帧协议格式', '1', '2025-06-12 22:55:46', '1', '2025-06-12 22:55:46', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2012, 'MES 客户类型', 'mes_client_type', 0, '', '1', '2026-02-15 14:38:25', '1', '2026-02-15 14:38:25', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2013, 'MES 供应商级别', 'mes_vendor_level', 0, '', '1', '2026-02-15 15:59:15', '1', '2026-02-15 15:59:15', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2014, 'MES 假期类型', 'mes_cal_holiday_type', 0, 'MES 日历排班 - 假期类型(HOLIDAY=假期,WORKDAY=工作日)', '1', '2026-02-16 07:35:58', '1', '2026-02-16 07:35:58', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2015, 'MES 工具状态', 'mes_tm_tool_status', 0, 'MES 工具管理 - 工具状态(1=在库,2=领用中,3=维修中,4=报废)', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2016, 'MES 保养维护类型', 'mes_tm_mainten_type', 0, 'MES 工具管理 - 保养维护类型(1=定期维护,2=按使用次数维护)', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2017, 'MES 设备状态', 'mes_dv_machinery_status', 0, 'MES 设备管理 - 设备状态(1=运行中,2=停机,3=故障)', '1', '2026-02-17 01:00:06', '1', '2026-02-17 01:00:06', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2018, 'MES 检测项类型', 'mes_indicator_type', 0, '', '1', '2026-02-17 02:16:22', '1', '2026-02-21 15:25:04', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2019, 'MES 缺陷等级', 'mes_defect_level', 0, '', '1', '2026-02-17 02:16:22', '1', '2026-02-17 02:16:22', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2020, 'MES 轮班方式', 'mes_cal_shift_type', 0, 'MES 日历排班 - 轮班方式', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2021, 'MES 倒班方式', 'mes_cal_shift_method', 0, 'MES 日历排班 - 倒班方式', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2022, 'MES 班组类型', 'mes_cal_calendar_type', 0, 'MES 日历排班 - 班组类型', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2023, 'MES 排班计划状态', 'mes_cal_plan_status', 0, 'MES 日历排班 - 排班计划状态', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2026, 'MES 检测种类', 'mes_qc_type', 0, 'IQC/IPQC/OQC/RQC', '1', '2026-02-17 08:34:40', '1', '2026-02-17 08:34:40', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2027, 'MES 生产工单状态', 'mes_pro_work_order_status', 0, 'MES 生产管理 - 工单状态(0=草稿,1=已确认,2=已完成,3=已取消)', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2028, 'MES 工单来源类型', 'mes_pro_work_order_source_type', 0, 'MES 生产管理 - 工单来源类型(1=客户订单,2=库存备货)', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2029, 'MES 工单类型', 'mes_pro_work_order_type', 0, 'MES 生产管理 - 工单类型(1=自行生产,2=代工,3=采购)', '1', '2026-02-17 11:43:47', '1', '2026-02-17 11:43:47', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2036, 'MES 工序关系类型', 'mes_pro_link_type', 0, '工艺路线中工序之间的关系类型', '1', '2026-02-19 04:24:53', '1', '2026-04-05 15:05:07', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2037, 'MES 时间单位', 'mes_time_unit_type', 0, '生产时间的计量单位', '1', '2026-02-19 04:24:53', '1', '2026-04-05 15:04:57', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2038, 'MES 生产任务状态', 'mes_pro_task_status', 0, 'MES 生产管理 - 任务状态(0=草稿,1=进行中,2=暂停,3=已完成,4=已取消)', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2039, 'MES 点检保养项目类型', 'mes_dv_subject_type', 0, 'MES 设备管理 - 点检保养项目类型(1=设备点检,2=设备保养)', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2040, 'MES 保养记录状态', 'mes_mainten_record_status', 0, NULL, 'admin', '2026-02-20 02:59:55', 'admin', '2026-02-20 02:59:55', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2041, 'MES 保养结果', 'mes_mainten_status', 0, NULL, 'admin', '2026-02-20 02:59:55', 'admin', '2026-02-20 02:59:55', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2042, 'MES 点检保养周期类型', 'mes_dv_cycle_type', 0, 'MES 设备管理 - 点检保养周期类型(1=天,2=周,3=月,4=年)', '1', '2026-02-20 07:11:43', '1', '2026-02-20 07:11:43', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2043, 'MES 点检保养方案状态', 'mes_dv_check_plan_status', 0, 'MES 设备管理 - 点检保养方案状态(0=草稿,1=已启用)', '1', '2026-02-20 07:11:43', '1', '2026-02-20 07:11:43', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2044, 'MES 点检记录状态', 'mes_dv_check_record_status', 0, NULL, 'admin', '2026-02-20 09:46:19', 'admin', '2026-02-20 09:46:19', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2045, 'MES 点检结果', 'mes_dv_check_result', 0, NULL, 'admin', '2026-02-20 09:46:19', 'admin', '2026-02-20 09:46:19', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2046, 'MES 维修工单状态', 'mes_dv_repair_status', 0, 'MES 设备管理 - 维修工单状态(10=待维修,20=维修中,30=已完成,40=已验收)', '1', '2026-02-20 10:56:24', '1', '2026-02-20 10:56:24', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2047, 'MES 维修结果', 'mes_dv_repair_result', 0, 'MES 设备管理 - 维修结果(1=修复成功,2=报废)', '1', '2026-02-20 10:56:24', '1', '2026-02-20 10:56:24', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2049, 'MES 检测结果', 'mes_qc_check_result', 0, '来料检验的最终结果判定', '1', '2026-02-20 11:23:35', '1', '2026-02-20 11:23:35', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2050, 'MES 来源单据类型', 'mes_qc_source_doc_type', 0, 'IQC 来料检验的来源单据类型', '1', '2026-02-20 11:23:35', '1', '2026-02-20 11:23:35', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2051, 'MES 安灯处置状态', 'mes_pro_andon_status', 0, 'MES 生产管理 - 安灯处置状态(0=未处置,1=已处置)', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2052, 'MES 安灯级别', 'mes_pro_andon_level', 0, 'MES 生产管理 - 安灯级别(1=一级,2=二级,3=三级)', '1', '2026-02-21 00:08:38', '1', '2026-02-21 00:08:38', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2053, 'MES 生产报工状态', 'mes_pro_feedback_status', 0, 'MES 生产管理 - 报工状态(0=草稿,1=审批中,2=待检验,3=已完成,4=已取消)', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2054, 'MES 生产报工类型', 'mes_pro_feedback_type', 0, 'MES 生产管理 - 报工类型(1=自行报工,2=统一报工)', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2055, 'MES 生产报工途径', 'mes_pro_feedback_channel', 0, 'MES 生产管理 - 报工途径(PC/APP/PDA)', '1', '2026-02-21 00:50:32', '1', '2026-02-21 00:50:32', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2056, 'MES 质检值类型', 'mes_qc_result_type', 0, '检验结果明细的值类型:浮点/整数/文本/字典/文件', '1', '2026-02-21 13:37:17', '1', '2026-02-21 13:37:17', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2057, 'MES 退货检验类型', 'mes_rqc_type', 0, 'MES 退货检验类型', '1', '2026-02-22 06:43:18', '1', '2026-02-22 06:43:18', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2062, 'MES IPQC 检验类型', 'mes_ipqc_type', 0, 'IPQC 过程检验的检验类型', '1', '2026-02-22 07:01:04', '1', '2026-02-22 07:01:04', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2066, 'MES 到货通知单状态', 'mes_wm_arrival_notice_status', 0, 'MES 到货通知单状态', '1', '2026-02-22 14:53:18', '1', '2026-02-22 14:53:18', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2067, 'MES 采购入库单状态', 'mes_wm_item_receipt_status', 0, 'MES 采购入库单状态', '1', '2026-02-22 14:54:05', '1', '2026-02-22 14:54:05', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2068, 'MES 单据状态', 'mes_order_status', 0, '', '1', '2026-02-23 21:16:03', '1', '2026-02-23 21:17:37', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2069, 'MES 领料出库单状态', 'mes_wm_product_issue_status', 0, 'MES 领料出库单状态', '1', '2026-02-26 16:39:44', '1', '2026-04-05 15:05:11', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2073, 'MES 生产退料单状态', 'mes_wm_return_issue_status', 0, 'MES 生产退料单状态', '1', '2026-02-28 14:11:09', '1', '2026-04-05 15:05:14', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2074, 'MES 生产退料类型', 'mes_wm_return_issue_type', 0, 'MES 生产退料类型', '1', '2026-02-28 14:11:09', '1', '2026-04-05 15:05:16', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2075, 'MES 质量状态', 'mes_wm_quality_status', 0, 'MES 质量状态(待检/合格/不合格)', '1', '2026-02-28 15:00:53', '1', '2026-02-28 15:00:53', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2100, 'MES 产品入库单状态', 'mes_wm_product_receipt_status', 0, 'MES 产品入库单状态', '1', '2026-03-01 06:03:04', '1', '2026-04-05 15:05:49', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2102, 'MES 销售出库单状态', 'mes_wm_product_sales_status', 0, 'MES 销售出库单状态', '1', '2026-03-02 08:55:11', '1', '2026-04-05 15:05:18', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2105, 'MES 杂项入库类型', 'mes_wm_misc_receipt_type', 0, '杂项入库类型', '1', '2026-03-03 07:18:12', '1', '2026-04-05 15:05:23', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2106, 'MES 杂项入库状态', 'mes_wm_misc_receipt_status', 0, '杂项入库状态', '1', '2026-03-03 07:18:12', '1', '2026-04-05 15:05:25', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2109, 'MES 杂项出库类型', 'mes_wm_misc_issue_type', 0, 'MES 杂项出库类型', '1', '2026-03-03 07:34:33', '1', '2026-03-03 07:34:33', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2110, 'MES 外协入库单状态', 'mes_wm_outsource_receipt_status', 0, 'MES 外协入库单状态', '1', '2026-03-03 14:03:20', '1', '2026-03-03 14:03:20', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2112, 'MES 外协发料单状态', 'mes_wm_outsource_issue_status', 0, 'MES 外协发料单状态', '1', '2026-03-03 16:30:56', '1', '2026-04-05 15:05:47', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2113, 'MES 编码规则分段类型', 'mes_md_auto_code_part_type', 0, 'MES 编码规则分段类型', '1', '2026-03-04 14:45:46', '1', '2026-03-04 15:24:40', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2115, 'MES 编码规则补齐方式', 'mes_md_auto_code_padded_method', 0, 'MES 编码规则补齐方式', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2116, 'MES 编码规则循环方式', 'mes_md_auto_code_cycle_method', 0, 'MES 编码规则循环方式', '1', '2026-03-04 14:46:22', '1', '2026-03-04 15:24:40', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2117, 'MES 条码格式', 'mes_wm_barcode_format', 0, 'MES 条码格式', '1', '2026-03-05 14:37:20', '1', '2026-04-05 15:05:27', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2118, 'MES 条码业务类型', 'mes_wm_barcode_biz_type', 0, 'MES 条码业务类型', '1', '2026-03-05 14:37:20', '1', '2026-04-05 15:05:29', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2121, 'MES 装箱单状态', 'mes_wm_package_status', 0, 'MES 装箱单状态', '1', '2026-03-08 02:05:46', '1', '2026-04-05 15:05:35', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2122, 'MES 调拨单状态', 'mes_wm_transfer_status', 0, 'MES 调拨单状态', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2123, 'MES 调拨类型', 'mes_wm_transfer_type', 0, 'MES 调拨类型', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2124, 'MES 盘点类型', 'mes_wm_stock_taking_type', 0, 'MES 盘点类型', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2125, 'MES 盘点方案参数类型', 'mes_wm_stock_taking_plan_param_type', 0, 'MES 盘点方案参数类型', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2126, 'MES 盘点任务状态', 'mes_wm_stock_taking_task_status', 0, 'MES 盘点任务状态', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2127, 'MES 盘点任务行状态', 'mes_wm_stock_taking_task_line_status', 0, 'MES 盘点任务行状态', '1', '2026-03-09 00:00:00', '1', '2026-04-05 15:02:18', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2129, 'MES 物料产品标识', 'mes_md_item_or_product', 0, '物料分类:物料(ITEM) / 产品(PRODUCT)', '1', '2026-03-15 01:55:06', '1', '2026-03-15 01:55:06', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2130, 'MES 供应商退货单状态', 'mes_wm_return_vendor_status', 0, '采购退货单状态', '', '2026-03-29 13:49:57', '', '2026-04-05 15:53:46', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2131, 'MES 发货通知单状态', 'mes_wm_sales_notice_status', 0, 'MES 发货通知单状态', '1', '2026-03-30 08:54:30', '1', '2026-04-05 15:53:46', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2132, 'MES 杂项出库单状态', 'mes_wm_misc_issue_status', 0, '杂项出库单状态', '1', '2026-03-30 15:00:18', '1', '2026-04-05 15:05:41', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2133, 'MES 销售退货单状态', 'mes_wm_return_sales_status', 0, 'MES 销售退货单状态枚举', '1', '2026-04-03 17:20:25', '1', '2026-04-05 15:05:39', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2134, 'MES 缺陷检测项类型', 'mes_defect_type', 0, '缺陷模块的检测项类型字典', '1', '2026-04-04 12:49:51', '1', '2026-04-04 12:49:51', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2135, 'MES 上下工状态类型', 'mes_pro_work_record_type', 0, 'MES 上下工状态类型', '1', '2026-04-05 14:07:27', '1', '2026-04-05 14:07:27', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (2138, 'MES 生产入库单状态', 'mes_wm_product_produce_status', 0, 'MES 生产入库单状态', '1', '2026-04-05 15:53:46', '1', '2026-04-05 15:53:46', b'0', '1970-01-01 00:00:00'); COMMIT; -- ---------------------------- @@ -1265,8 +1615,10 @@ CREATE TABLE `system_login_log` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 4449 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_username`(`username` ASC) USING BTREE, + INDEX `idx_create_time`(`create_time` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4486 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -1399,7 +1751,7 @@ CREATE TABLE `system_menu` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 5049 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; +) ENGINE = InnoDB AUTO_INCREMENT = 5986 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; -- ---------------------------- -- Records of system_menu @@ -2341,6 +2693,391 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5044, '删除模版消息', 'mp:message-template:delete', 3, 2, 5042, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-11-26 17:00:31', '1', '2025-11-26 18:45:05', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5045, '同步公众号模板', 'mp:message-template:sync', 3, 3, 5042, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-11-26 17:00:55', '1', '2025-11-26 17:00:55', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5046, '给粉丝发送模版消息', 'mp:message-template:send', 3, 4, 5042, '', '', '', '', 0, b'1', b'1', b'1', '1', '2025-11-26 17:01:11', '1', '2025-11-26 17:01:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5100, 'MES 系统', '', 1, 500, 0, '/mes', 'ep:cpu', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:39:57', '1', '2026-04-05 23:22:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5101, '基础数据', '', 1, 10, 5100, 'md', 'ep:data-analysis', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5110, '物料产品分类', '', 2, 2, 5101, 'item-type', 'ep:files', 'mes/md/item/type/index', 'MesMdItemType', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 13:58:29', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5111, '分类查询', 'mes:md-item-type:query', 3, 1, 5110, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5112, '分类创建', 'mes:md-item-type:create', 3, 2, 5110, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5113, '分类更新', 'mes:md-item-type:update', 3, 3, 5110, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5114, '分类删除', 'mes:md-item-type:delete', 3, 4, 5110, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5120, '物料产品管理', '', 2, 1, 5101, 'item', 'ep:box', 'mes/md/item/index', 'MesMdItem', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 13:58:24', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5121, '物料查询', 'mes:md-item:query', 3, 1, 5120, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5122, '物料创建', 'mes:md-item:create', 3, 2, 5120, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5123, '物料更新', 'mes:md-item:update', 3, 3, 5120, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5124, '物料删除', 'mes:md-item:delete', 3, 4, 5120, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5125, '物料导出', 'mes:md-item:export', 3, 5, 5120, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 00:40:13', '1', '2026-02-15 00:40:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5126, '物料导入', 'mes:md-item:import', 3, 6, 5120, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 14:13:01', '1', '2026-02-15 14:13:01', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5130, '计量单位', '', 2, 3, 5101, 'unit-measure', 'ep:scale-to-original', 'mes/md/unitmeasure/index', 'MesMdUnitMeasure', 0, b'1', b'1', b'1', '1', '2026-02-15 13:55:01', '1', '2026-02-15 13:55:01', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5131, '单位查询', 'mes:md-unit-measure:query', 3, 1, 5130, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 13:55:16', '1', '2026-02-15 13:55:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5132, '单位创建', 'mes:md-unit-measure:create', 3, 2, 5130, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 13:55:16', '1', '2026-02-15 13:55:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5133, '单位更新', 'mes:md-unit-measure:update', 3, 3, 5130, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 13:55:16', '1', '2026-02-15 13:55:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5134, '单位删除', 'mes:md-unit-measure:delete', 3, 4, 5130, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 13:55:16', '1', '2026-02-15 13:55:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5135, '单位导出', 'mes:md-unit-measure:export', 3, 5, 5130, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 13:55:16', '1', '2026-02-15 13:55:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5140, '客户管理', '', 2, 4, 5101, 'client', 'ep:user', 'mes/md/client/index', 'MesMdClient', 0, b'1', b'1', b'1', '1', '2026-02-15 15:06:41', '1', '2026-02-15 15:06:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5141, '客户查询', 'mes:md-client:query', 3, 1, 5140, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 15:06:41', '1', '2026-02-15 15:06:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5142, '客户创建', 'mes:md-client:create', 3, 2, 5140, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 15:06:41', '1', '2026-02-15 15:06:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5143, '客户更新', 'mes:md-client:update', 3, 3, 5140, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 15:06:41', '1', '2026-02-15 15:06:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5144, '客户删除', 'mes:md-client:delete', 3, 4, 5140, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 15:06:41', '1', '2026-02-15 15:06:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5145, '客户导出', 'mes:md-client:export', 3, 5, 5140, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 15:06:41', '1', '2026-02-15 15:06:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5146, '客户导入', 'mes:md-client:import', 3, 6, 5140, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 15:06:41', '1', '2026-02-15 15:06:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5150, '供应商管理', '', 2, 5, 5101, 'vendor', 'ep:goods', 'mes/md/vendor/index', 'MesMdVendor', 0, b'1', b'1', b'1', '1', '2026-02-15 16:01:11', '1', '2026-02-15 16:01:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5151, '供应商查询', 'mes:md-vendor:query', 3, 1, 5150, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:01:11', '1', '2026-02-15 16:01:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5152, '供应商创建', 'mes:md-vendor:create', 3, 2, 5150, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:01:11', '1', '2026-02-15 16:01:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5153, '供应商更新', 'mes:md-vendor:update', 3, 3, 5150, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:01:11', '1', '2026-02-15 16:01:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5154, '供应商删除', 'mes:md-vendor:delete', 3, 4, 5150, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:01:11', '1', '2026-02-15 16:01:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5155, '供应商导出', 'mes:md-vendor:export', 3, 5, 5150, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:01:11', '1', '2026-02-15 16:01:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5156, '供应商导入', 'mes:md-vendor:import', 3, 6, 5150, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:01:11', '1', '2026-02-15 16:01:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5160, '车间设置', '', 2, 6, 5101, 'workstation/workshop', 'ep:office-building', 'mes/md/workstation/workshop/index', 'MesMdWorkshop', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-16 11:17:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5161, '车间查询', 'mes:md-workshop:query', 3, 1, 5160, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5162, '车间创建', 'mes:md-workshop:create', 3, 2, 5160, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5163, '车间更新', 'mes:md-workshop:update', 3, 3, 5160, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5164, '车间删除', 'mes:md-workshop:delete', 3, 4, 5160, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5170, '工作站设置', '', 2, 7, 5101, 'workstation', 'ep:place', 'mes/md/workstation/index', 'MesMdWorkstation', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-16 11:18:34', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5171, '工位查询', 'mes:md-workstation:query', 3, 1, 5170, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5172, '工位创建', 'mes:md-workstation:create', 3, 2, 5170, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5173, '工位更新', 'mes:md-workstation:update', 3, 3, 5170, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5174, '工位删除', 'mes:md-workstation:delete', 3, 4, 5170, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5175, '工位导出', 'mes:md-workstation:export', 3, 5, 5170, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-15 16:47:47', '1', '2026-02-15 16:47:47', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5190, '编码规则', '', 2, 10, 5101, 'auto-code', 'ep:document', 'mes/md/autocode/index', 'MesAutoCode', 0, b'1', b'1', b'1', '1', '2026-03-04 05:26:04', '1', '2026-04-03 08:31:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5191, '编码规则查询', 'mes:auto-code-rule:query', 3, 1, 5190, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-04 05:26:04', '1', '2026-03-04 05:26:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5192, '编码规则创建', 'mes:auto-code-rule:create', 3, 2, 5190, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-04 05:26:04', '1', '2026-03-04 05:26:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5193, '编码规则更新', 'mes:auto-code-rule:update', 3, 3, 5190, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-04 05:26:04', '1', '2026-03-04 05:26:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5194, '编码规则删除', 'mes:auto-code-rule:delete', 3, 4, 5190, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-04 05:26:04', '1', '2026-03-04 05:26:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5195, '编码规则导出', 'mes:auto-code-rule:export', 3, 5, 5190, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-04 05:26:04', '1', '2026-03-04 05:26:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5200, '排班管理', '', 1, 70, 5100, 'cal', 'ep:calendar', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 07:35:50', '1', '2026-02-16 15:37:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5220, '班组设置', '', 2, 1, 5200, 'team', 'ep:user', 'mes/cal/team/index', 'MesCalTeam', 0, b'1', b'1', b'1', '1', '2026-02-18 01:16:03', '1', '2026-02-18 11:14:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5221, '班组查询', 'mes:cal-team:query', 3, 1, 5220, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-18 01:16:03', '1', '2026-02-18 01:16:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5222, '班组创建', 'mes:cal-team:create', 3, 2, 5220, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-18 01:16:03', '1', '2026-02-18 01:16:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5223, '班组更新', 'mes:cal-team:update', 3, 3, 5220, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-18 01:16:03', '1', '2026-02-18 01:16:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5224, '班组删除', 'mes:cal-team:delete', 3, 4, 5220, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-18 01:16:03', '1', '2026-02-18 01:16:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5225, '班组导出', 'mes:cal-team:export', 3, 5, 5220, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-18 01:16:03', '1', '2026-02-18 01:16:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5230, '排班计划', '', 2, 3, 5200, 'plan', 'ep:memo', 'mes/cal/plan/index', 'MesCalPlan', 0, b'1', b'1', b'1', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5231, '排班计划查询', 'mes:cal-plan:query', 3, 1, 5230, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5232, '排班计划创建', 'mes:cal-plan:create', 3, 2, 5230, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5233, '排班计划更新', 'mes:cal-plan:update', 3, 3, 5230, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5234, '排班计划删除', 'mes:cal-plan:delete', 3, 4, 5230, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5235, '排班计划导出', 'mes:cal-plan:export', 3, 5, 5230, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 03:40:09', '1', '2026-02-17 03:40:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5250, '节假日设置', '', 2, 3, 5200, 'holiday', 'ep:sunny', 'mes/cal/holiday/index', 'MesCalHoliday', 0, b'1', b'1', b'1', '1', '2026-02-16 07:35:50', '1', '2026-02-16 15:38:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5251, '假期查询', 'mes:cal-holiday:query', 3, 1, 5250, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 07:35:50', '1', '2026-02-16 07:35:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5252, '假期创建', 'mes:cal-holiday:create', 3, 2, 5250, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 07:35:50', '1', '2026-02-16 07:35:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5253, '假期更新', 'mes:cal-holiday:update', 3, 3, 5250, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 07:35:50', '1', '2026-02-16 07:35:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5254, '假期删除', 'mes:cal-holiday:delete', 3, 4, 5250, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 07:35:50', '1', '2026-02-16 07:35:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5255, '假期导出', 'mes:cal-holiday:export', 3, 5, 5250, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 07:35:50', '1', '2026-02-16 07:35:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5260, '排班日历', '', 2, 3, 5200, 'calendar', 'ep:calendar', 'mes/cal/calendar/index', 'MesCalCalendar', 0, b'1', b'1', b'1', '1', '2026-02-19 04:19:33', '1', '2026-02-19 04:19:33', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5261, '排班日历查询', 'mes:cal-team-shift:query', 3, 1, 5260, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 04:19:33', '1', '2026-02-19 04:19:33', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5300, '设备管理', '', 1, 30, 5100, 'dv', 'ep:cpu', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 09:01:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5310, '设备类型', '', 2, 1, 5300, 'machinery/type', 'ep:files', 'mes/dv/machinery/type/index', 'MesDvMachineryType', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 09:02:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5311, '类型查询', 'mes:dv-machinery-type:query', 3, 1, 5310, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5312, '类型创建', 'mes:dv-machinery-type:create', 3, 2, 5310, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5313, '类型更新', 'mes:dv-machinery-type:update', 3, 3, 5310, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5314, '类型删除', 'mes:dv-machinery-type:delete', 3, 4, 5310, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5315, '类型导出', 'mes:dv-machinery-type:export', 3, 5, 5310, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5320, '设备台账', '', 2, 2, 5300, 'machinery', 'ep:monitor', 'mes/dv/machinery/index', 'MesDvMachinery', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5321, '设备查询', 'mes:dv-machinery:query', 3, 1, 5320, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5322, '设备创建', 'mes:dv-machinery:create', 3, 2, 5320, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5323, '设备更新', 'mes:dv-machinery:update', 3, 3, 5320, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5324, '设备删除', 'mes:dv-machinery:delete', 3, 4, 5320, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5325, '设备导出', 'mes:dv-machinery:export', 3, 5, 5320, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 00:59:58', '1', '2026-02-17 00:59:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5326, '设备导入', 'mes:dv-machinery:import', 3, 6, 5320, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-04-02 15:40:42', '1', '2026-04-02 15:40:42', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5330, '点检保养项目', '', 2, 3, 5300, 'subject', 'ep:document-checked', 'mes/dv/subject/index', 'MesDvSubject', 0, b'1', b'1', b'1', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5331, '项目查询', 'mes:dv-subject:query', 3, 1, 5330, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5332, '项目创建', 'mes:dv-subject:create', 3, 2, 5330, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5333, '项目更新', 'mes:dv-subject:update', 3, 3, 5330, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5334, '项目删除', 'mes:dv-subject:delete', 3, 4, 5330, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5335, '项目导出', 'mes:dv-subject:export', 3, 5, 5330, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:42:58', '1', '2026-02-20 01:42:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5340, '保养记录', '', 2, 6, 5300, 'mainten-record', 'ep:setting', 'mes/dv/maintenrecord/index', 'MesDvMaintenRecord', 0, b'1', b'1', b'1', '', '2026-02-20 02:59:55', '1', '2026-03-02 11:45:39', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5341, '保养记录查询', 'mes:dv-mainten-record:query', 3, 1, 5340, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 02:59:55', '', '2026-02-20 02:59:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5342, '保养记录创建', 'mes:dv-mainten-record:create', 3, 2, 5340, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 02:59:55', '', '2026-02-20 02:59:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5343, '保养记录更新', 'mes:dv-mainten-record:update', 3, 3, 5340, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 02:59:55', '', '2026-02-20 02:59:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5344, '保养记录删除', 'mes:dv-mainten-record:delete', 3, 4, 5340, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 02:59:55', '', '2026-02-20 02:59:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5345, '保养记录导出', 'mes:dv-mainten-record:export', 3, 5, 5340, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 02:59:55', '', '2026-02-20 02:59:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5350, '点检保养方案', '', 2, 4, 5300, 'checkplan', 'ep:calendar', 'mes/dv/checkplan/index', 'MesDvCheckPlan', 0, b'1', b'1', b'1', '1', '2026-02-20 07:13:08', '1', '2026-02-20 07:13:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5351, '方案查询', 'mes:dv-check-plan:query', 3, 1, 5350, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 07:13:08', '1', '2026-02-20 07:13:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5352, '方案创建', 'mes:dv-check-plan:create', 3, 2, 5350, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 07:13:08', '1', '2026-02-20 07:13:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5353, '方案更新', 'mes:dv-check-plan:update', 3, 3, 5350, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 07:13:08', '1', '2026-02-20 07:13:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5354, '方案删除', 'mes:dv-check-plan:delete', 3, 4, 5350, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 07:13:08', '1', '2026-02-20 07:13:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5355, '方案导出', 'mes:dv-check-plan:export', 3, 5, 5350, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 07:13:08', '1', '2026-02-20 07:13:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5360, '点检记录', '', 2, 5, 5300, 'check-record', 'ep:document-checked', 'mes/dv/checkrecord/index', 'MesDvCheckRecord', 0, b'1', b'1', b'1', '', '2026-02-20 09:46:19', '', '2026-03-02 11:45:39', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5361, '点检记录查询', 'mes:dv-check-record:query', 3, 1, 5360, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 09:46:19', '', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5362, '点检记录创建', 'mes:dv-check-record:create', 3, 2, 5360, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 09:46:19', '', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5363, '点检记录更新', 'mes:dv-check-record:update', 3, 3, 5360, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 09:46:19', '', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5364, '点检记录删除', 'mes:dv-check-record:delete', 3, 4, 5360, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 09:46:19', '', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5365, '点检记录导出', 'mes:dv-check-record:export', 3, 5, 5360, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-02-20 09:46:19', '', '2026-02-20 09:46:19', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5366, '工单导出', 'mes:dv-repair:export', 3, 5, 5360, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:07:06', '1', '2026-02-20 11:07:06', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5370, '维修单', '', 2, 7, 5300, 'repair', 'ep:tools', 'mes/dv/repair/index', 'MesDvRepair', 0, b'1', b'1', b'1', '1', '2026-02-20 11:06:28', '1', '2026-02-20 19:10:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5371, '工单查询', 'mes:dv-repair:query', 3, 1, 5370, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:06:28', '1', '2026-02-20 11:06:28', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5372, '工单创建', 'mes:dv-repair:create', 3, 2, 5370, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:06:28', '1', '2026-02-20 11:06:28', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5373, '工单更新', 'mes:dv-repair:update', 3, 3, 5370, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:54:20', '1', '2026-02-20 11:54:20', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5374, '工单删除', 'mes:dv-repair:delete', 3, 4, 5370, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:54:15', '1', '2026-02-20 11:54:15', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5375, '工单导出', 'mes:dv-repair:export', 3, 5, 5370, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:54:04', '1', '2026-02-20 11:54:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5400, '工具管理', '', 1, 40, 5100, 'tm', 'ep:scissor', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-03-21 14:20:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5410, '工具类型设置', '', 2, 1, 5400, 'tool/type', 'ep:files', 'mes/tm/tool/type/index', 'MesTmToolType', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 21:28:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5411, '类型查询', 'mes:tm-tool-type:query', 3, 1, 5410, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5412, '类型创建', 'mes:tm-tool-type:create', 3, 2, 5410, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5413, '类型更新', 'mes:tm-tool-type:update', 3, 3, 5410, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5414, '类型删除', 'mes:tm-tool-type:delete', 3, 4, 5410, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5415, '类型导出', 'mes:tm-tool-type:export', 3, 5, 5410, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5420, '工装夹具台账', '', 2, 2, 5400, 'tool', 'ep:box', 'mes/tm/tool/index', 'MesTmTool', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 21:29:23', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5421, '工具查询', 'mes:tm-tool:query', 3, 1, 5420, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5422, '工具创建', 'mes:tm-tool:create', 3, 2, 5420, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5423, '工具更新', 'mes:tm-tool:update', 3, 3, 5420, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5424, '工具删除', 'mes:tm-tool:delete', 3, 4, 5420, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5425, '工具导出', 'mes:tm-tool:export', 3, 5, 5420, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-16 11:10:55', '1', '2026-02-16 11:10:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5500, '质量管理', '', 1, 60, 5100, 'qc', 'ep:check', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 02:18:18', '1', '2026-02-17 14:36:15', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5510, '常见缺陷', '', 2, 1, 5500, 'defect', 'ep:warning', 'mes/qc/defect/index', 'MesQcDefect', 0, b'1', b'1', b'1', '1', '2026-02-17 02:18:18', '1', '2026-03-04 04:29:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5511, '缺陷类型查询', 'mes:qc-defect:query', 3, 1, 5510, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 02:18:18', '1', '2026-02-17 02:18:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5512, '缺陷类型创建', 'mes:qc-defect:create', 3, 2, 5510, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 02:18:18', '1', '2026-02-17 02:18:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5513, '缺陷类型更新', 'mes:qc-defect:update', 3, 3, 5510, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 02:18:18', '1', '2026-02-17 02:18:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5514, '缺陷类型删除', 'mes:qc-defect:delete', 3, 4, 5510, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 02:18:18', '1', '2026-02-17 02:18:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5515, '缺陷类型导出', 'mes:qc-defect:export', 3, 5, 5510, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 02:18:18', '1', '2026-02-17 02:18:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5530, '生产工单', '', 2, 1, 5700, 'work-order', 'ep:document-copy', 'mes/pro/workorder/index', 'MesProWorkOrder', 0, b'1', b'1', b'1', '1', '2026-02-17 11:51:44', '1', '2026-02-17 19:54:36', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5531, '工单查询', 'mes:pro-work-order:query', 3, 1, 5530, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:51:44', '1', '2026-02-17 11:51:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5532, '工单创建', 'mes:pro-work-order:create', 3, 2, 5530, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:51:44', '1', '2026-02-17 11:51:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5533, '工单更新', 'mes:pro-work-order:update', 3, 3, 5530, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:51:44', '1', '2026-02-17 11:51:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5534, '工单删除', 'mes:pro-work-order:delete', 3, 4, 5530, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:51:44', '1', '2026-02-17 11:51:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5535, '工单导出', 'mes:pro-work-order:export', 3, 5, 5530, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:51:44', '1', '2026-02-17 11:51:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5540, '生产排产', '', 2, 4, 5700, 'task', 'ep:calendar', 'mes/pro/task/index', 'MesProTask', 0, b'1', b'1', b'1', '1', '2026-02-19 15:25:27', '1', '2026-02-20 08:30:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5541, '排产查询', 'mes:pro-task:query', 3, 1, 5540, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5542, '排产创建', 'mes:pro-task:create', 3, 2, 5540, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5543, '排产更新', 'mes:pro-task:update', 3, 3, 5540, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5544, '排产删除', 'mes:pro-task:delete', 3, 4, 5540, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5545, '排产导出', 'mes:pro-task:export', 3, 5, 5540, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 15:25:27', '1', '2026-02-19 15:25:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5550, '生产报工', '', 2, 5, 5700, 'feedback', 'ep:finished', 'mes/pro/feedback/index', 'MesProFeedback', 0, b'1', b'1', b'1', '1', '2026-02-21 00:50:22', '1', '2026-02-21 08:55:14', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5551, '报工查询', 'mes:pro-feedback:query', 3, 1, 5550, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:50:22', '1', '2026-02-21 00:50:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5552, '报工创建', 'mes:pro-feedback:create', 3, 2, 5550, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:50:22', '1', '2026-02-21 00:50:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5553, '报工更新', 'mes:pro-feedback:update', 3, 3, 5550, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:50:22', '1', '2026-02-21 00:50:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5554, '报工删除', 'mes:pro-feedback:delete', 3, 4, 5550, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:50:22', '1', '2026-02-21 00:50:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5555, '报工导出', 'mes:pro-feedback:export', 3, 5, 5550, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:50:22', '1', '2026-02-21 00:50:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5560, '工序流转', '', 2, 6, 5700, 'card', 'ep:postcard', 'mes/pro/card/index', 'MesProCard', 0, b'1', b'1', b'1', '1', '2026-02-21 03:16:35', '1', '2026-02-21 11:18:42', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5561, '流转卡查询', 'mes:pro-card:query', 3, 1, 5560, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 03:16:35', '1', '2026-02-21 03:16:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5562, '流转卡创建', 'mes:pro-card:create', 3, 2, 5560, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 03:16:35', '1', '2026-02-21 03:16:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5563, '流转卡更新', 'mes:pro-card:update', 3, 3, 5560, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 03:16:35', '1', '2026-02-21 03:16:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5564, '流转卡删除', 'mes:pro-card:delete', 3, 4, 5560, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 03:16:35', '1', '2026-02-21 03:16:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5565, '流转卡导出', 'mes:pro-card:export', 3, 5, 5560, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 03:16:35', '1', '2026-02-21 03:16:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5566, '流转卡完成', 'mes:pro-card:finish', 3, 6, 5560, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-04-04 12:18:15', '1', '2026-04-04 12:18:15', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5610, '检测项设置', '', 2, 2, 5500, 'indicator', 'ep:data-analysis', 'mes/qc/indicator/index', 'MesQcIndicator', 0, b'1', b'1', b'1', '1', '2026-02-17 08:11:31', '1', '2026-02-17 16:16:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5611, '质检指标查询', 'mes:qc-indicator:query', 3, 1, 5610, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:11:31', '1', '2026-02-17 08:11:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5612, '质检指标创建', 'mes:qc-indicator:create', 3, 2, 5610, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:11:31', '1', '2026-02-17 08:11:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5613, '质检指标更新', 'mes:qc-indicator:update', 3, 3, 5610, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:11:31', '1', '2026-02-17 08:11:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5614, '质检指标删除', 'mes:qc-indicator:delete', 3, 4, 5610, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:11:31', '1', '2026-02-17 08:11:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5615, '质检指标导出', 'mes:qc-indicator:export', 3, 5, 5610, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:11:31', '1', '2026-02-17 08:11:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5630, '质检方案', '', 2, 3, 5500, 'template', 'ep:document-copy', 'mes/qc/template/index', 'MesQcTemplate', 0, b'1', b'1', b'1', '1', '2026-02-17 08:34:40', '1', '2026-03-04 04:29:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5631, '质检方案查询', 'mes:qc-template:query', 3, 1, 5630, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:34:40', '1', '2026-02-18 14:12:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5632, '质检方案创建', 'mes:qc-template:create', 3, 2, 5630, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:34:40', '1', '2026-02-18 14:12:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5633, '质检方案更新', 'mes:qc-template:update', 3, 3, 5630, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:34:40', '1', '2026-02-18 14:12:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5634, '质检方案删除', 'mes:qc-template:delete', 3, 4, 5630, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:34:40', '1', '2026-02-18 14:12:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5635, '质检方案导出', 'mes:qc-template:export', 3, 5, 5630, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 08:34:40', '1', '2026-02-18 14:12:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5640, '来料检验', '', 2, 5, 5500, 'iqc', 'ep:finished', 'mes/qc/iqc/index', 'MesQcIqc', 0, b'1', b'1', b'1', '1', '2026-02-20 11:23:45', '1', '2026-02-24 05:24:01', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5641, '来料检验查询', 'mes:qc-iqc:query', 3, 1, 5640, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:23:45', '1', '2026-02-20 11:23:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5642, '来料检验创建', 'mes:qc-iqc:create', 3, 2, 5640, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:23:45', '1', '2026-02-20 11:23:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5643, '来料检验更新', 'mes:qc-iqc:update', 3, 3, 5640, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:23:45', '1', '2026-02-20 11:23:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5644, '来料检验删除', 'mes:qc-iqc:delete', 3, 4, 5640, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:23:45', '1', '2026-02-20 11:23:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5645, '来料检验导出', 'mes:qc-iqc:export', 3, 5, 5640, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 11:23:45', '1', '2026-02-20 11:23:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5650, '过程检验', '', 2, 6, 5500, 'ipqc', 'ep:checked', 'mes/qc/ipqc/index', 'MesQcIpqc', 0, b'1', b'1', b'1', '1', '2026-02-22 07:01:08', '1', '2026-02-22 15:02:42', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5651, '过程检验查询', 'mes:qc-ipqc:query', 3, 1, 5650, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 07:01:08', '1', '2026-02-22 07:01:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5652, '过程检验创建', 'mes:qc-ipqc:create', 3, 2, 5650, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 07:01:08', '1', '2026-02-22 07:01:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5653, '过程检验更新', 'mes:qc-ipqc:update', 3, 3, 5650, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 07:01:08', '1', '2026-02-22 07:01:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5654, '过程检验删除', 'mes:qc-ipqc:delete', 3, 4, 5650, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 07:01:08', '1', '2026-02-22 07:01:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5655, '过程检验导出', 'mes:qc-ipqc:export', 3, 5, 5650, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 07:01:08', '1', '2026-02-22 07:01:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5660, '出货检验', '', 2, 8, 5500, 'oqc', 'ep:sell', 'mes/qc/oqc/index', 'MesQcOqc', 0, b'1', b'1', b'1', '1', '2026-02-22 06:55:53', '1', '2026-02-22 14:58:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5661, '出货检验查询', 'mes:qc-oqc:query', 3, 1, 5660, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:55:53', '1', '2026-02-22 06:55:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5662, '出货检验创建', 'mes:qc-oqc:create', 3, 2, 5660, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:55:53', '1', '2026-02-22 06:55:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5663, '出货检验更新', 'mes:qc-oqc:update', 3, 3, 5660, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:55:53', '1', '2026-02-22 06:55:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5664, '出货检验删除', 'mes:qc-oqc:delete', 3, 4, 5660, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:55:53', '1', '2026-02-22 06:55:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5665, '出货检验导出', 'mes:qc-oqc:export', 3, 5, 5660, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:55:53', '1', '2026-02-22 06:55:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5670, '退料检验', '', 2, 7, 5500, 'rqc', 'ep:warning-filled', 'mes/qc/rqc/index', 'MesQcRqc', 0, b'1', b'1', b'1', '1', '2026-02-22 06:43:25', '1', '2026-02-22 14:46:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5671, '退货检验查询', 'mes:qc-rqc:query', 3, 1, 5670, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:43:25', '1', '2026-02-22 06:43:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5672, '退货检验创建', 'mes:qc-rqc:create', 3, 2, 5670, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:43:25', '1', '2026-02-22 06:43:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5673, '退货检验更新', 'mes:qc-rqc:update', 3, 3, 5670, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:43:25', '1', '2026-02-22 06:43:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5674, '退货检验删除', 'mes:qc-rqc:delete', 3, 4, 5670, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:43:25', '1', '2026-02-22 06:43:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5675, '退货检验导出', 'mes:qc-rqc:export', 3, 5, 5670, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 06:43:25', '1', '2026-02-22 06:43:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5680, '待检任务', '', 2, 4, 5500, 'pending-inspect', 'ep:clock', 'mes/qc/pendinginspect/index', 'MesQcPendingInspect', 0, b'1', b'1', b'1', '1', '2026-02-23 07:15:41', '1', '2026-02-24 05:24:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5681, '待检任务查询', 'mes:qc-pending-inspect:query', 3, 1, 5680, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-23 07:15:41', '1', '2026-02-23 07:15:41', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5700, '生产管理', '', 1, 50, 5100, 'pro', 'ep:management', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:39:58', '1', '2026-02-17 19:53:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5710, '工序设置', '', 2, 2, 5700, 'process', 'ep:operation', 'mes/pro/process/index', 'MesProProcess', 0, b'1', b'1', b'1', '1', '2026-02-17 11:39:58', '1', '2026-02-19 16:23:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5711, '工序查询', 'mes:pro-process:query', 3, 1, 5710, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:39:58', '1', '2026-02-17 11:39:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5712, '工序创建', 'mes:pro-process:create', 3, 2, 5710, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:39:58', '1', '2026-02-17 11:39:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5713, '工序更新', 'mes:pro-process:update', 3, 3, 5710, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:39:58', '1', '2026-02-17 11:39:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5714, '工序删除', 'mes:pro-process:delete', 3, 4, 5710, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:39:58', '1', '2026-02-17 11:39:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5715, '工序导出', 'mes:pro-process:export', 3, 5, 5710, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 11:39:58', '1', '2026-02-17 11:39:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5720, '工艺流程', '', 2, 3, 5700, 'route', 'ep:guide', 'mes/pro/route/index', 'MesProRoute', 0, b'1', b'1', b'1', '1', '2026-02-19 04:24:53', '1', '2026-02-19 16:24:23', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5721, '工艺路线查询', 'mes:pro-route:query', 3, 1, 5720, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5722, '工艺路线创建', 'mes:pro-route:create', 3, 2, 5720, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5723, '工艺路线更新', 'mes:pro-route:update', 3, 3, 5720, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5724, '工艺路线删除', 'mes:pro-route:delete', 3, 4, 5720, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5725, '工艺路线导出', 'mes:pro-route:export', 3, 5, 5720, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5750, '安灯呼叫', '', 2, 7, 5700, 'andon', 'ep:bell', 'mes/pro/andon/record/index', 'MesProAndonRecord', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 11:35:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5751, '安灯记录查询', 'mes:pro-andon-record:query', 3, 1, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5752, '安灯记录创建', 'mes:pro-andon-record:create', 3, 2, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5753, '安灯记录更新', 'mes:pro-andon-record:update', 3, 3, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5754, '安灯记录删除', 'mes:pro-andon-record:delete', 3, 4, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5755, '安灯记录导出', 'mes:pro-andon-record:export', 3, 5, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5756, '安灯配置查询', 'mes:pro-andon-config:query', 3, 6, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5757, '安灯配置创建', 'mes:pro-andon-config:create', 3, 7, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5758, '安灯配置更新', 'mes:pro-andon-config:update', 3, 8, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5759, '安灯配置删除', 'mes:pro-andon-config:delete', 3, 9, 5750, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-21 00:24:18', '1', '2026-02-21 00:24:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5780, '仓库管理', '', 1, 20, 5100, 'wm', 'ep:box', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 15:37:58', '1', '2026-02-17 23:38:18', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5781, '仓库设置', '', 2, 1, 5780, 'warehouse', 'ep:office-building', 'mes/wm/warehouse/index', 'MesWmWarehouse', 0, b'1', b'1', b'1', '1', '2026-02-17 15:37:58', '1', '2026-02-17 15:37:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5782, '仓库查询', 'mes:wm-warehouse:query', 3, 1, 5781, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 15:37:58', '1', '2026-02-17 15:37:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5783, '仓库创建', 'mes:wm-warehouse:create', 3, 2, 5781, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 15:37:58', '1', '2026-02-17 15:37:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5784, '仓库更新', 'mes:wm-warehouse:update', 3, 3, 5781, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 15:37:58', '1', '2026-02-17 15:37:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5785, '仓库删除', 'mes:wm-warehouse:delete', 3, 4, 5781, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-17 15:37:58', '1', '2026-02-17 15:37:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5786, '库存现有量', '', 2, 2, 5780, 'material-stock', 'ep:document', 'mes/wm/materialstock/index', 'MesWmMaterialStock', 0, b'1', b'1', b'1', '1', '2026-02-20 01:02:36', '1', '2026-02-20 09:03:40', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5787, '库存台账查询', 'mes:wm-material-stock:query', 3, 1, 5786, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:02:36', '1', '2026-02-20 01:02:36', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5788, '库存台账创建', 'mes:wm-material-stock:create', 3, 2, 5786, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:02:37', '1', '2026-02-20 01:02:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5789, '库存台账更新', 'mes:wm-material-stock:update', 3, 3, 5786, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:02:37', '1', '2026-02-20 01:02:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5790, '库存台账删除', 'mes:wm-material-stock:delete', 3, 4, 5786, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:02:37', '1', '2026-02-20 01:02:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5791, '库存台账导出', 'mes:wm-material-stock:export', 3, 5, 5786, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-20 01:02:37', '1', '2026-02-20 01:02:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5792, '到货通知', '', 2, 4, 5780, 'arrival-notice', 'ep:document-checked', 'mes/wm/arrivalnotice/index', 'MesWmArrivalNotice', 0, b'1', b'1', b'1', '1', '2026-02-22 09:11:05', '1', '2026-02-22 17:13:15', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5793, '到货通知单查询', 'mes:wm-arrival-notice:query', 3, 1, 5792, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 09:11:05', '1', '2026-02-22 09:11:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5794, '到货通知单创建', 'mes:wm-arrival-notice:create', 3, 2, 5792, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 09:11:05', '1', '2026-02-22 09:11:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5795, '到货通知单更新', 'mes:wm-arrival-notice:update', 3, 3, 5792, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 09:11:05', '1', '2026-02-22 09:11:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5796, '到货通知单删除', 'mes:wm-arrival-notice:delete', 3, 4, 5792, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 09:11:05', '1', '2026-02-22 09:11:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5797, '到货通知单导出', 'mes:wm-arrival-notice:export', 3, 5, 5792, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 09:11:05', '1', '2026-02-22 09:11:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5798, '采购入库', '', 2, 3, 5780, 'item-receipt', 'ep:goods', 'mes/wm/itemreceipt/index', 'MesWmItemReceipt', 0, b'1', b'1', b'1', '1', '2026-02-22 10:23:22', '1', '2026-02-22 18:35:01', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5799, '采购入库单查询', 'mes:wm-item-receipt:query', 3, 1, 5798, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 10:23:22', '1', '2026-02-22 10:23:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5800, '采购入库单创建', 'mes:wm-item-receipt:create', 3, 2, 5798, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 10:23:22', '1', '2026-02-22 10:23:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5801, '采购入库单更新', 'mes:wm-item-receipt:update', 3, 3, 5798, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 10:23:22', '1', '2026-02-22 10:23:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5802, '采购入库单删除', 'mes:wm-item-receipt:delete', 3, 4, 5798, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 10:23:22', '1', '2026-02-22 10:23:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5803, '采购入库单导出', 'mes:wm-item-receipt:export', 3, 5, 5798, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 10:23:22', '1', '2026-02-22 10:23:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5804, '采购入库单完成', 'mes:wm-item-receipt:finish', 3, 6, 5798, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-22 10:23:22', '1', '2026-03-02 11:24:29', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5805, '生产领料', '', 2, 6, 5780, 'product-issue', 'ep:sell', 'mes/wm/productissue/index', 'MesWmProductIssue', 0, b'1', b'1', b'1', '1', '2026-02-26 15:53:24', '1', '2026-03-23 12:21:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5806, '领料出库单查询', 'mes:wm-product-issue:query', 3, 1, 5805, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-26 15:53:24', '1', '2026-03-23 12:21:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5807, '领料出库单新增', 'mes:wm-product-issue:create', 3, 2, 5805, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-26 15:53:24', '1', '2026-03-23 12:21:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5808, '领料出库单修改', 'mes:wm-product-issue:update', 3, 3, 5805, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-26 15:53:24', '1', '2026-03-23 12:21:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5809, '领料出库单删除', 'mes:wm-product-issue:delete', 3, 4, 5805, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-26 15:53:24', '1', '2026-03-23 12:21:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5810, '领料出库单导出', 'mes:wm-product-issue:export', 3, 5, 5805, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-26 15:53:24', '1', '2026-03-23 12:21:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5811, '领料出库单完成', 'mes:wm-product-issue:finish', 3, 6, 5805, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-26 15:53:24', '1', '2026-03-30 03:06:32', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5819, '产品入库', '', 2, 8, 5780, 'product-receipt', 'ep:box', 'mes/wm/productreceipt/index', 'MesWmProductReceipt', 0, b'1', b'1', b'1', '1', '2026-03-01 04:03:25', '1', '2026-03-04 04:29:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5820, '产品入库单查询', 'mes:wm-product-receipt:query', 3, 1, 5819, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 04:03:25', '1', '2026-03-01 06:03:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5821, '产品入库单新增', 'mes:wm-product-receipt:create', 3, 2, 5819, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 04:03:25', '1', '2026-03-01 06:03:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5822, '产品入库单修改', 'mes:wm-product-receipt:update', 3, 3, 5819, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 04:03:25', '1', '2026-03-01 06:03:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5823, '产品入库单删除', 'mes:wm-product-receipt:delete', 3, 4, 5819, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 04:03:25', '1', '2026-03-01 06:03:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5824, '产品入库单导出', 'mes:wm-product-receipt:export', 3, 5, 5819, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 04:03:25', '1', '2026-03-01 06:03:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5825, '产品入库单完成', 'mes:wm-product-receipt:finish', 3, 6, 5819, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 04:03:25', '1', '2026-03-02 11:24:29', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5830, '采购退货', '', 2, 5, 5780, 'return-vendor', 'ep:box', 'mes/wm/returnvendor/index', 'MesWmReturnVendor', 0, b'1', b'1', b'1', '1', '2026-02-28 09:47:48', '1', '2026-03-29 20:22:49', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5831, '供应商退货单查询', 'mes:wm-return-vendor:query', 3, 1, 5830, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 09:47:48', '1', '2026-02-28 09:47:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5832, '供应商退货单新增', 'mes:wm-return-vendor:create', 3, 2, 5830, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 09:47:48', '1', '2026-02-28 09:47:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5833, '供应商退货单修改', 'mes:wm-return-vendor:update', 3, 3, 5830, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 09:47:48', '1', '2026-02-28 09:47:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5834, '供应商退货单删除', 'mes:wm-return-vendor:delete', 3, 4, 5830, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 09:47:48', '1', '2026-02-28 09:47:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5835, '供应商退货单导出', 'mes:wm-return-vendor:export', 3, 5, 5830, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 09:47:48', '1', '2026-02-28 09:47:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5836, '供应商退货单状态变更', 'mes:wm-return-vendor:update-status', 3, 6, 5830, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 09:47:48', '1', '2026-02-28 09:47:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5840, '生产退料', '', 2, 7, 5780, 'return-issue', 'ep:refresh-left', 'mes/wm/returnissue/index', 'MesWmReturnIssue', 0, b'1', b'1', b'1', '1', '2026-02-28 14:11:04', '1', '2026-03-04 04:29:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5841, '生产退料单查询', 'mes:wm-return-issue:query', 3, 1, 5840, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 14:11:04', '1', '2026-02-28 14:11:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5842, '生产退料单新增', 'mes:wm-return-issue:create', 3, 2, 5840, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 14:11:04', '1', '2026-02-28 14:11:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5843, '生产退料单修改', 'mes:wm-return-issue:update', 3, 3, 5840, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 14:11:04', '1', '2026-02-28 14:11:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5844, '生产退料单删除', 'mes:wm-return-issue:delete', 3, 4, 5840, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 14:11:04', '1', '2026-02-28 14:11:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5845, '生产退料单导出', 'mes:wm-return-issue:export', 3, 5, 5840, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-02-28 14:11:04', '1', '2026-02-28 14:11:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5846, '生产退料单执行', 'mes:wm-return-issue:finish', 3, 6, 5840, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-02-28 14:11:04', '1', '2026-03-02 11:24:30', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5847, '销售退货', '', 2, 11, 5780, 'return-sales', 'ep:refresh-left', 'mes/wm/returnsales/index', 'MesWmReturnSales', 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-04 04:29:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5848, '销售退货单查询', 'mes:wm-return-sales:query', 3, 1, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-01 10:31:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5849, '销售退货单新增', 'mes:wm-return-sales:create', 3, 2, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-01 10:31:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5850, '销售退货单修改', 'mes:wm-return-sales:update', 3, 3, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-01 10:31:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5851, '销售退货单删除', 'mes:wm-return-sales:delete', 3, 4, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-01 10:31:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5852, '销售退货单导出', 'mes:wm-return-sales:export', 3, 5, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-01 10:31:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5853, '销售退货单提交', 'mes:wm-return-sales:submit', 3, 6, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-01 10:31:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5854, '销售退货单完成退货', 'mes:wm-return-sales:finish', 3, 7, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-02 11:24:29', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5855, '销售退货单执行上架', 'mes:wm-return-sales:stock', 3, 8, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-01 10:31:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5856, '销售退货单取消', 'mes:wm-return-sales:cancel', 3, 9, 5847, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-01 10:31:35', '1', '2026-03-01 10:31:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5857, '杂项出库', '', 2, 20, 5780, 'misc-issue', 'ep:sell', 'mes/wm/miscissue/index', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:33:34', '1', '2026-03-03 09:12:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5858, '杂项出库查询', 'mes:wm-misc-issue:query', 3, 1, 5857, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:33:34', '1', '2026-03-02 14:33:34', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5859, '杂项出库新增', 'mes:wm-misc-issue:create', 3, 2, 5857, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:33:34', '1', '2026-03-02 14:33:34', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5860, '杂项出库修改', 'mes:wm-misc-issue:update', 3, 3, 5857, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:33:34', '1', '2026-03-02 14:33:34', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5861, '杂项出库删除', 'mes:wm-misc-issue:delete', 3, 4, 5857, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:33:34', '1', '2026-03-02 14:33:34', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5862, '杂项出库导出', 'mes:wm-misc-issue:export', 3, 5, 5857, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:33:34', '1', '2026-03-02 14:33:34', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5863, '杂项出库执行', 'mes:wm-misc-issue:finish', 3, 6, 5857, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:33:34', '1', '2026-03-02 14:33:34', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5867, '发货通知', '', 2, 9, 5780, 'sales-notice', 'fa-solid:notes-medical', 'mes/wm/salesnotice/index', 'MesWmSalesNotice', 0, b'1', b'1', b'1', '1', '2026-03-30 08:54:30', '1', '2026-03-30 17:09:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5868, '查询发货通知', 'mes:wm-sales-notice:query', 3, 1, 5867, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-30 08:54:30', '1', '2026-03-30 16:57:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5869, '创建发货通知', 'mes:wm-sales-notice:create', 3, 2, 5867, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-30 08:54:30', '1', '2026-03-30 16:57:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5870, '更新发货通知', 'mes:wm-sales-notice:update', 3, 3, 5867, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-30 08:54:30', '1', '2026-03-30 16:57:49', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5871, '删除发货通知', 'mes:wm-sales-notice:delete', 3, 4, 5867, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-30 08:54:30', '1', '2026-03-30 16:57:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5872, '导出发货通知', 'mes:wm-sales-notice:export', 3, 5, 5867, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-30 08:54:30', '1', '2026-03-30 16:58:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5873, '外协入库', '', 2, 18, 5780, 'outsource-receipt', 'fa-solid:truck', 'mes/wm/outsourcereceipt/index', 'MesWmOutsourceReceipt', 0, b'1', b'1', b'1', '1', '2026-03-31 15:36:37', '1', '2026-04-01 00:04:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5874, '外协入库单查询', 'mes:wm-outsource-receipt:query', 3, 1, 5873, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-31 15:36:37', '1', '2026-03-31 15:36:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5875, '外协入库单新增', 'mes:wm-outsource-receipt:create', 3, 2, 5873, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-31 15:36:37', '1', '2026-03-31 15:36:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5876, '外协入库单修改', 'mes:wm-outsource-receipt:update', 3, 3, 5873, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-31 15:36:37', '1', '2026-03-31 15:36:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5877, '外协入库单删除', 'mes:wm-outsource-receipt:delete', 3, 4, 5873, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-31 15:36:37', '1', '2026-03-31 15:36:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5878, '外协入库单导出', 'mes:wm-outsource-receipt:export', 3, 5, 5873, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-31 15:36:37', '1', '2026-03-31 15:36:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5879, '外协入库单完成', 'mes:wm-outsource-receipt:finish', 3, 6, 5873, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-31 15:36:37', '1', '2026-03-31 15:36:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5881, '外协发料', '', 2, 17, 5780, 'outsource-issue', 'ep:sell', 'mes/wm/outsourceissue/index', 'MesWmOutsourceIssue', 0, b'1', b'1', b'1', '1', '2026-03-02 14:36:04', '1', '2026-03-03 19:59:38', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5882, '外协发料单查询', 'mes:wm-outsource-issue:query', 3, 1, 5881, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:36:04', '1', '2026-03-02 14:36:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5883, '外协发料单新增', 'mes:wm-outsource-issue:create', 3, 2, 5881, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:36:04', '1', '2026-03-02 14:36:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5884, '外协发料单修改', 'mes:wm-outsource-issue:update', 3, 3, 5881, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:36:04', '1', '2026-03-02 14:36:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5885, '外协发料单删除', 'mes:wm-outsource-issue:delete', 3, 4, 5881, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:36:04', '1', '2026-03-02 14:36:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5886, '外协发料单导出', 'mes:wm-outsource-issue:export', 3, 5, 5881, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:36:04', '1', '2026-03-02 14:36:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5887, '外协发料单执行出库', 'mes:wm-outsource-issue:execute', 3, 6, 5881, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-02 14:36:04', '1', '2026-03-02 14:36:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5888, '杂项入库', '', 2, 19, 5780, 'misc-receipt', 'ep:bottom', 'mes/wm/miscreceipt/index', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:46:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5889, '杂项入库查询', 'mes:wm:misc-receipt:query', 3, 1, 5888, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:17:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5890, '杂项入库创建', 'mes:wm:misc-receipt:create', 3, 2, 5888, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:17:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5891, '杂项入库更新', 'mes:wm:misc-receipt:update', 3, 3, 5888, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:17:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5892, '杂项入库删除', 'mes:wm:misc-receipt:delete', 3, 4, 5888, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:17:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5893, '杂项入库提交', 'mes:wm:misc-receipt:submit', 3, 5, 5888, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:17:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5894, '杂项入库执行', 'mes:wm:misc-receipt:finish', 3, 6, 5888, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:17:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5895, '杂项入库取消', 'mes:wm:misc-receipt:cancel', 3, 7, 5888, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:17:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5896, '杂项入库导出', 'mes:wm:misc-receipt:export', 3, 8, 5888, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-03 07:17:50', '1', '2026-03-03 07:17:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5897, 'SN 码', '', 2, 16, 5780, 'sn', 'ep:document', 'mes/wm/sn/index', 'MesWmSn', 0, b'1', b'1', b'1', '1', '2026-03-05 01:30:21', '1', '2026-03-05 13:37:30', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5898, 'SN 码查询', 'mes:wm-sn:query', 3, 1, 5897, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-05 01:30:21', '1', '2026-03-05 01:30:21', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5899, 'SN 码生成', 'mes:wm-sn:create', 3, 2, 5897, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-05 01:30:21', '1', '2026-03-05 01:30:21', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5900, 'SN 码删除', 'mes:wm-sn:delete', 3, 4, 5897, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-05 01:30:21', '1', '2026-03-05 01:30:21', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5901, 'SN 码导出', 'mes:wm-sn:export', 3, 5, 5897, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-05 01:30:21', '1', '2026-03-05 01:30:21', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5906, '条码配置', '', 2, 15, 5780, 'barcode/config', 'fa:barcode', 'mes/wm/barcode/config/index', 'MesWmBarcodeConfig', 0, b'0', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 21:05:20', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5907, '条码配置查询', 'mes:wm-barcode-config:query', 3, 1, 5906, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 21:09:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5908, '条码配置创建', 'mes:wm-barcode-config:create', 3, 2, 5906, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 21:09:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5909, '条码配置更新', 'mes:wm-barcode-config:update', 3, 3, 5906, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 21:09:21', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5910, '条码配置删除', 'mes:wm-barcode-config:delete', 3, 4, 5906, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 21:09:26', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5911, '赋能管理', '', 2, 15, 5780, 'barcode', 'fa:qrcode', 'mes/wm/barcode/index', 'MesWmBarcode', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 10:01:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5912, '条码清单查询', 'mes:wm-barcode:query', 3, 1, 5911, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 09:58:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5913, '条码清单创建', 'mes:wm-barcode:create', 3, 2, 5911, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 09:59:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5914, '条码清单更新', 'mes:wm-barcode:update', 3, 3, 5911, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 09:59:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5915, '条码清单删除', 'mes:wm-barcode:delete', 3, 4, 5911, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-05 14:37:20', '1', '2026-03-06 09:59:12', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5916, '条码清单导出', 'mes:wm-barcode:export', 3, 5, 5911, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-07 02:08:17', '1', '2026-03-07 02:08:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5917, '装箱管理', '', 2, 14, 5780, 'packages', 'ep:box', 'mes/wm/packages/index', 'MesWmPackages', 0, b'1', b'1', b'1', '1', '2026-03-08 02:05:46', '1', '2026-03-08 19:16:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5918, '装箱管理查询', 'mes:wm-package:query', 3, 1, 5917, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-08 02:05:46', '1', '2026-03-08 02:05:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5919, '装箱管理新增', 'mes:wm-package:create', 3, 2, 5917, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-08 02:05:46', '1', '2026-03-08 02:05:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5920, '装箱管理修改', 'mes:wm-package:update', 3, 3, 5917, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-08 02:05:46', '1', '2026-03-08 02:05:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5921, '装箱管理删除', 'mes:wm-package:delete', 3, 4, 5917, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-08 02:05:46', '1', '2026-03-08 02:05:46', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5922, '转移调拨', '', 2, 12, 5780, 'transfer', 'ep:sort', 'mes/wm/transfer/index', 'MesWmTransfer', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-22 15:22:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5923, '调拨单查询', 'mes:wm-transfer:query', 3, 1, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5924, '调拨单新增', 'mes:wm-transfer:create', 3, 2, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5925, '调拨单修改', 'mes:wm-transfer:update', 3, 3, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5926, '调拨单删除', 'mes:wm-transfer:delete', 3, 4, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5927, '调拨单导出', 'mes:wm-transfer:export', 3, 5, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5928, '调拨单提交', 'mes:wm-transfer:submit', 3, 6, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5929, '调拨单确认', 'mes:wm-transfer:confirm', 3, 7, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5930, '调拨单完成', 'mes:wm-transfer:finish', 3, 8, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5931, '调拨单取消', 'mes:wm-transfer:cancel', 3, 9, 5922, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-08 11:55:25', '1', '2026-03-08 11:55:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5950, '库存盘点', '', 1, 13, 5780, 'stock-taking', 'ep:circle-check-filled', '', '', 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 21:19:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5951, '盘点方案', '', 2, 1, 5950, 'plan', 'ep:document', 'mes/wm/stocktaking/plan/index', 'MesWmStockTakingPlan', 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 13:19:52', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5952, '盘点方案查询', 'mes:wm-stock-taking-plan:query', 3, 1, 5951, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 13:35:06', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5953, '盘点方案创建', 'mes:wm-stock-taking-plan:create', 3, 2, 5951, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 13:35:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5954, '盘点方案更新', 'mes:wm-stock-taking-plan:update', 3, 3, 5951, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 13:35:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5955, '盘点方案删除', 'mes:wm-stock-taking-plan:delete', 3, 4, 5951, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 13:35:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5956, '盘点方案导出', 'mes:wm-stock-taking-plan:export', 3, 5, 5951, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 13:35:13', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5957, '盘点任务', '', 2, 2, 5950, 'task', 'ep:list', 'mes/wm/stocktaking/task/index', 'MesWmStockTakingTask', 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 23:00:02', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5958, '盘点任务查询', 'mes:wm-stock-taking-task:query', 3, 1, 5957, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5959, '盘点任务创建', 'mes:wm-stock-taking-task:create', 3, 2, 5957, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5960, '盘点任务更新', 'mes:wm-stock-taking-task:update', 3, 3, 5957, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5961, '盘点任务删除', 'mes:wm-stock-taking-task:delete', 3, 4, 5957, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5962, '盘点任务导出', 'mes:wm-stock-taking-task:export', 3, 5, 5957, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-09 00:00:00', '1', '2026-03-09 00:00:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5966, '批次追溯', '', 2, 9, 5500, 'batch-trace', 'ep:aim', 'mes/qc/batchtrace/index', 'BatchTrace', 0, b'1', b'1', b'1', '1', '2026-03-14 06:59:25', '1', '2026-04-05 09:39:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5967, '批次追溯查询', 'mes:wm-batch:query', 3, 1, 5966, '', '', '', NULL, 0, b'1', b'1', b'1', '1', '2026-03-14 06:59:25', '1', '2026-03-14 06:59:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5969, '报告审批', 'mes:pro-feedback:approve', 3, 6, 5550, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-03-19 08:51:16', '1', '2026-03-19 08:51:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5970, '销售出库', '', 2, 10, 5780, 'product-sales', 'ep:sell', 'mes/wm/productsales/index', 'MesWmProductSales', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5971, '查询销售出库', 'mes:wm-product-sales:query', 3, 1, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5972, '创建销售出库', 'mes:wm-product-sales:create', 3, 2, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5973, '更新销售出库', 'mes:wm-product-sales:update', 3, 3, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5974, '删除销售出库', 'mes:wm-product-sales:delete', 3, 4, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5975, '导出销售出库', 'mes:wm-product-sales:export', 3, 5, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5976, '提交销售出库', 'mes:wm-product-sales:submit', 3, 6, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5977, '执行拣货', 'mes:wm-product-sales:stock', 3, 7, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5978, '填写运单', 'mes:wm-product-sales:shipping', 3, 8, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5979, '执行出库', 'mes:wm-product-sales:finish', 3, 9, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5980, '取消销售出库', 'mes:wm-product-sales:cancel', 3, 10, 5970, '', '', '', '', 0, b'1', b'1', b'1', '', '2026-03-30 10:37:08', '', '2026-03-30 10:37:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5981, '工作记录', '', 2, 99, 5700, 'workrecord', 'ep:timer', 'mes/pro/workrecord/index', 'MesProWorkRecordLog', 0, b'1', b'1', b'1', '1', '2026-04-05 14:08:44', '1', '2026-04-05 14:08:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5982, '工作记录查询', 'mes:pro-workrecord:query', 3, 1, 5981, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-04-05 14:08:44', '1', '2026-04-05 14:08:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5983, '工作记录导出', 'mes:pro-workrecord:export', 3, 2, 5981, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-04-05 14:08:44', '1', '2026-04-05 14:08:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5984, '上工下工', 'mes:pro-workrecord:clock', 3, 3, 5981, '', '', '', '', 0, b'1', b'1', b'1', '1', '2026-04-05 14:08:44', '1', '2026-04-05 14:08:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (5985, 'MES 首页', 'mes:home:query', 2, 0, 5100, 'mes/home/index', 'ep:home-filled', 'mes/home/index', 'MesHome', 0, b'1', b'1', b'1', '1', '2026-04-05 23:24:03', '1', '2026-04-06 01:20:52', b'0'); COMMIT; -- ---------------------------- @@ -2393,7 +3130,8 @@ CREATE TABLE `system_notify_message` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_user_id_user_type_read_status`(`user_id` ASC, `user_type` ASC, `read_status` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '站内信消息表'; -- ---------------------------- @@ -2462,7 +3200,7 @@ CREATE TABLE `system_oauth2_access_token` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_access_token`(`access_token` ASC) USING BTREE, INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 47630 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 49915 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -2488,7 +3226,8 @@ CREATE TABLE `system_oauth2_approve` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_user_id_user_type_client_id`(`user_id` ASC, `user_type` ASC, `client_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 84 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 批准表'; -- ---------------------------- @@ -2523,7 +3262,8 @@ CREATE TABLE `system_oauth2_client` ( `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_client_id`(`client_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 43 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 客户端表'; -- ---------------------------- @@ -2556,7 +3296,8 @@ CREATE TABLE `system_oauth2_code` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_code`(`code` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 155 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 授权码表'; -- ---------------------------- @@ -2583,8 +3324,9 @@ CREATE TABLE `system_oauth2_refresh_token` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2501 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2527 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -2617,7 +3359,9 @@ CREATE TABLE `system_operate_log` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_user_id`(`user_id` ASC) USING BTREE, + INDEX `idx_create_time`(`create_time` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 9193 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本'; -- ---------------------------- @@ -2705,8 +3449,9 @@ CREATE TABLE `system_role_menu` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 6352 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色和菜单关联表'; + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_role_id`(`role_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 6365 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '角色和菜单关联表'; -- ---------------------------- -- Records of system_role_menu @@ -3585,6 +4330,19 @@ INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_t INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6349, 2, 1221, '1', '2026-01-04 18:09:41', '1', '2026-01-04 18:09:41', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6350, 2, 1222, '1', '2026-01-04 18:09:41', '1', '2026-01-04 18:09:41', b'0', 1); INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6351, 2, 2913, '1', '2026-01-04 18:09:41', '1', '2026-01-04 18:09:41', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6352, 1, 5720, '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6353, 1, 5721, '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6354, 1, 5722, '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6355, 1, 5723, '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6356, 1, 5724, '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6357, 1, 5725, '1', '2026-02-19 04:24:53', '1', '2026-02-19 04:24:53', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6358, 1, 5811, '', '2026-03-30 03:11:59', '', '2026-03-30 03:11:59', b'0', 0); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6359, 1, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6360, 2, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6361, 3, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 1); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6362, 109, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 121); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6363, 111, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 122); +INSERT INTO `system_role_menu` (`id`, `role_id`, `menu_id`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (6364, 155, 5811, '', '2026-03-30 03:13:05', '', '2026-03-30 03:13:05', b'0', 1); COMMIT; -- ---------------------------- @@ -3791,7 +4549,9 @@ CREATE TABLE `system_social_user` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_type_openid`(`type` ASC, `openid` ASC) USING BTREE, + INDEX `idx_type_code_state`(`type` ASC, `code` ASC, `state` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 40 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交用户表'; -- ---------------------------- @@ -3816,7 +4576,8 @@ CREATE TABLE `system_social_user_bind` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_user_type_social_user_id`(`user_type` ASC, `social_user_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 165 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '社交绑定表'; -- ---------------------------- @@ -3930,7 +4691,8 @@ CREATE TABLE `system_user_role` ( `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_user_id`(`user_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 55 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户和角色关联表'; -- ---------------------------- @@ -3985,14 +4747,18 @@ CREATE TABLE `system_users` ( `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 NOT NULL DEFAULT 0 COMMENT '租户编号', - PRIMARY KEY (`id`) USING BTREE + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_username`(`username` ASC) USING BTREE, + INDEX `idx_mobile`(`mobile` ASC) USING BTREE, + INDEX `idx_email`(`email` ASC) USING BTREE, + INDEX `idx_dept_id`(`dept_id` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 145 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户信息表'; -- ---------------------------- -- Records of system_users -- ---------------------------- BEGIN; -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$04$.vd8nPeLwxt6hnSzmAoAyul8BOLX7Cib6QhcxRe30rfvrIPQHH1OG', '芋道源码', '管理员', 103, '[1,2]', '13aoteman@126.com', '18818260272', 1, 'http://test.yudao.iocoder.cn/user/avatar/20251220/blob_1766215463801.jpg', 0, '0:0:0:0:0:0:0:1', '2026-02-14 09:07:33', 'admin', '2021-01-05 17:03:47', NULL, '2026-02-14 09:07:33', b'0', 1); +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$04$.vd8nPeLwxt6hnSzmAoAyul8BOLX7Cib6QhcxRe30rfvrIPQHH1OG', '芋道源码', '管理员', 103, '[1,2]', '13aoteman@126.com', '18818260272', 1, 'http://test.yudao.iocoder.cn/user/avatar/20251220/blob_1766215463801.jpg', 0, '127.0.0.1', '2026-03-27 18:50:21', 'admin', '2021-01-05 17:03:47', NULL, '2026-03-27 18:50:21', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$04$h.aaPKgO.odHepnk5PCsWeEwKdojFWdTItxGKfx1r0e1CSeBzsTJ6', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2025-12-15 21:47:26', '', '2021-01-07 09:07:17', NULL, '2025-12-15 21:47:26', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$04$fUBSmjKCPYAUmnMzOb6qE.eZCGPhHi1JmAKclODbfS/O7fHOl2bH6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, NULL, 0, '0:0:0:0:0:0:0:1', '2024-08-11 17:48:12', '', '2021-01-13 23:50:35', '1', '2025-07-09 23:41:58', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$04$BrwaYn303hjA/6TnXqdGoOLhyHOAA0bVrAFu6.1dJKycqKUnIoRz2', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, NULL, 0, '0:0:0:0:0:0:0:1', '2026-01-04 18:09:54', '', '2021-01-21 02:13:53', NULL, '2026-01-04 18:09:54', b'0', 1); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index aa523b94d..28265a5d5 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -349,4 +349,27 @@ public class CollectionUtils { return (LinkedHashSet) toCollection(LinkedHashSet.class, elementType, value); } + public static boolean dfs(Long node, Map> graph) { + return dfs(node, graph, new HashSet<>(), new HashSet<>()); + } + + private static boolean dfs(Long node, Map> graph, Set visited, Set inStack) { + if (inStack.contains(node)) { + return true; + } + if (visited.contains(node)) { + return false; + } + visited.add(node); + inStack.add(node); + Set neighbors = graph.getOrDefault(node, Collections.emptySet()); + for (Long neighbor : neighbors) { + if (dfs(neighbor, graph, visited, inStack)) { + return true; + } + } + inStack.remove(node); + return false; + } + } \ No newline at end of file diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 4cbd4b618..287cda2e3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -335,6 +335,27 @@ public class LocalDateTimeUtils { } } + /** + * 获取指定日期所在季度的第一天 + * + * @param date 日期 + * @return 所在季度的第一天 + */ + public static LocalDate getQuarterStart(LocalDate date) { + Month firstMonthOfQuarter = date.getMonth().firstMonthOfQuarter(); + return LocalDate.of(date.getYear(), firstMonthOfQuarter, 1); + } + + /** + * 获取指定日期所在周的第一天(周一) + * + * @param date 日期 + * @return 所在周的周一 + */ + public static LocalDate getWeekStart(LocalDate date) { + return date.with(DayOfWeek.MONDAY); + } + /** * 将给定的 {@link LocalDateTime} 转换为自 Unix 纪元时间(1970-01-01T00:00:00Z)以来的秒数。 * diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java index a26c7c12e..585858579 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/ObjectUtils.java @@ -60,6 +60,11 @@ public class ObjectUtils { return Arrays.asList(array).contains(obj); } + @SafeVarargs + public static boolean notEqualsAny(T obj, T... array) { + return !Arrays.asList(array).contains(obj); + } + public static boolean isNotAllEmpty(Object... objs) { return !ObjectUtil.isAllEmpty(objs); } diff --git a/yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java b/yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java index 08beaf808..a62aabb7a 100644 --- a/yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java +++ b/yudao-module-crm/yudao-module-crm-server/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java @@ -27,10 +27,12 @@ public interface CrmCustomerLimitConfigMapper extends BaseMapperX query = new LambdaQueryWrapperX() .eq(CrmCustomerLimitConfigDO::getType, type); - query.apply("FIND_IN_SET({0}, user_ids) > 0", userId); - if (deptId != null) { - query.apply("FIND_IN_SET({0}, dept_ids) > 0", deptId); - } + query.and(w -> { + w.apply("FIND_IN_SET({0}, user_ids) > 0", userId); + if (deptId != null) { + w.or().apply("FIND_IN_SET({0}, dept_ids) > 0", deptId); + } + }); return selectList(query); } diff --git a/yudao-module-mes/pom.xml b/yudao-module-mes/pom.xml new file mode 100644 index 000000000..e51f660ab --- /dev/null +++ b/yudao-module-mes/pom.xml @@ -0,0 +1,24 @@ + + + + cn.iocoder.cloud + yudao + ${revision} + + + yudao-module-mes-api + yudao-module-mes-server + + 4.0.0 + yudao-module-mes + pom + + ${project.artifactId} + + mes 包下,制造执行系统(Manufacturing Execution System)。 + 例如说:基础数据、排班日历、设备管理、工具管理、生产管理、质量管理、仓库管理等等 + + + diff --git a/yudao-module-mes/yudao-module-mes-api/pom.xml b/yudao-module-mes/yudao-module-mes-api/pom.xml new file mode 100644 index 000000000..29a6d9bf2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/pom.xml @@ -0,0 +1,33 @@ + + + + cn.iocoder.cloud + yudao-module-mes + ${revision} + + 4.0.0 + yudao-module-mes-api + jar + + ${project.artifactId} + + mes 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.cloud + yudao-common + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ApiConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ApiConstants.java new file mode 100644 index 000000000..fa678c6ee --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ApiConstants.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.mes.enums; + +import cn.iocoder.yudao.framework.common.enums.RpcConstants; + +/** + * API 相关的枚举 + * + * @author 芋道源码 + */ +public class ApiConstants { + + /** + * 服务名 + * + * 注意,需要保证和 spring.application.name 保持一致 + */ + public static final String NAME = "mes-server"; + + public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/mes"; + + public static final String VERSION = "1.0.0"; + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java new file mode 100644 index 000000000..ea234136e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.mes.enums; + +/** + * MES 字典类型的枚举类 + * + * @author 芋道源码 + */ +public interface DictTypeConstants { + + String MES_MD_ITEM_OR_PRODUCT = "mes_md_item_or_product"; // MES 物料产品标识 + String MES_CLIENT_TYPE = "mes_client_type"; // MES 客户类型 + String MES_VENDOR_LEVEL = "mes_vendor_level"; // MES 供应商级别 + String MES_CAL_HOLIDAY_TYPE = "mes_cal_holiday_type"; // MES 假期类型 + String MES_TM_TOOL_STATUS = "mes_tm_tool_status"; // MES 工具状态 + String MES_TM_MAINTEN_TYPE = "mes_tm_mainten_type"; // MES 保养维护类型 + String MES_CAL_SHIFT_TYPE = "mes_cal_shift_type"; // MES 轮班方式 + String MES_CAL_SHIFT_METHOD = "mes_cal_shift_method"; // MES 倒班方式 + String MES_CAL_CALENDAR_TYPE = "mes_cal_calendar_type"; // MES 班组类型 + String MES_CAL_PLAN_STATUS = "mes_cal_plan_status"; // MES 排班计划状态 + String MES_DV_MACHINERY_STATUS = "mes_dv_machinery_status"; // MES 设备状态 + String MES_DV_SUBJECT_TYPE = "mes_dv_subject_type"; // MES 点检保养项目类型 + String MES_INDICATOR_TYPE = "mes_indicator_type"; // MES 检测项类型 + String MES_QC_RESULT_TYPE = "mes_qc_result_type"; // MES 质检结果值类型 + String MES_DEFECT_TYPE = "mes_defect_type"; // MES 缺陷检测项类型 + String MES_DEFECT_LEVEL = "mes_defect_level"; // MES 缺陷等级 + String MES_PRO_WORK_ORDER_STATUS = "mes_pro_work_order_status"; // MES 生产工单状态 + String MES_PRO_WORK_ORDER_SOURCE_TYPE = "mes_pro_work_order_source_type"; // MES 工单来源类型 + String MES_PRO_WORK_ORDER_TYPE = "mes_pro_work_order_type"; // MES 工单类型 + String MES_QC_TYPE = "mes_qc_type"; // MES 检测种类(IQC/IPQC/OQC/RQC) + String MES_PRO_LINK_TYPE = "mes_pro_link_type"; // MES 工序关系类型 + String MES_TIME_UNIT_TYPE = "mes_time_unit_type"; // MES 时间单位 + String MES_IPQC_TYPE = "mes_ipqc_type"; // MES IPQC 检验类型 + String MES_ORDER_STATUS = "mes_order_status"; // MES 单据状态(IQC/IPQC/OQC/RQC 通用) + String MES_QC_CHECK_RESULT = "mes_qc_check_result"; // MES 检测结果 + String MES_QC_SOURCE_DOC_TYPE = "mes_qc_source_doc_type"; // MES 来源单据类型 + String MES_DV_CYCLE_TYPE = "mes_dv_cycle_type"; // MES 点检保养周期类型 + String MES_DV_CHECK_PLAN_STATUS = "mes_dv_check_plan_status"; // MES 点检保养方案状态 + String MES_MAINTEN_RECORD_STATUS = "mes_mainten_record_status"; // MES 保养记录状态 + String MES_MAINTEN_STATUS = "mes_mainten_status"; // MES 保养结果 + String MES_DV_CHECK_RECORD_STATUS = "mes_dv_check_record_status"; // MES 点检记录状态 + String MES_DV_CHECK_RESULT = "mes_dv_check_result"; // MES 点检结果 + String MES_DV_REPAIR_STATUS = "mes_dv_repair_status"; // MES 维修工单状态 + String MES_DV_REPAIR_RESULT = "mes_dv_repair_result"; // MES 维修结果 + String MES_PRO_ANDON_STATUS = "mes_pro_andon_status"; // MES 安灯处置状态 + String MES_PRO_ANDON_LEVEL = "mes_pro_andon_level"; // MES 安灯级别 + String MES_PRO_WORK_RECORD_TYPE = "mes_pro_work_record_type"; // MES 上下工状态类型 + String MES_PRO_FEEDBACK_STATUS = "mes_pro_feedback_status"; // MES 生产报工状态 + String MES_PRO_FEEDBACK_TYPE = "mes_pro_feedback_type"; // MES 生产报工类型 + String MES_PRO_FEEDBACK_CHANNEL = "mes_pro_feedback_channel"; // MES 生产报工途径 + String MES_WM_ARRIVAL_NOTICE_STATUS = "mes_wm_arrival_notice_status"; // MES 到货通知单状态 + String MES_WM_ITEM_RECEIPT_STATUS = "mes_wm_item_receipt_status"; // MES 采购入库单状态 + String MES_WM_PRODUCT_PRODUCE_STATUS = "mes_wm_product_produce_status"; // MES 生产入库单状态 + String MES_WM_RETURN_VENDOR_STATUS = "mes_wm_return_vendor_status"; // MES 供应商退货单状态 + String MES_WM_QUALITY_STATUS = "mes_wm_quality_status"; // MES 质量状态(待检/合格/不合格) + String MES_WM_RETURN_ISSUE_STATUS = "mes_wm_return_issue_status"; // MES 生产退料单状态 + String MES_WM_RETURN_ISSUE_TYPE = "mes_wm_return_issue_type"; // MES 生产退料类型 + String MES_WM_MISC_ISSUE_TYPE = "mes_wm_misc_issue_type"; // MES 杂项出库类型 + String MES_WM_MISC_ISSUE_STATUS = "mes_wm_misc_issue_status"; // MES 杂项出库单状态 + String MES_WM_SALES_NOTICE_STATUS = "mes_wm_sales_notice_status"; // MES 发货通知单状态 + String MES_WM_TRANSFER_STATUS = "mes_wm_transfer_status"; // MES 转移单状态 + String MES_WM_TRANSFER_TYPE = "mes_wm_transfer_type"; // MES 转移单类型 + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java new file mode 100644 index 000000000..aaee1b8f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -0,0 +1,647 @@ +package cn.iocoder.yudao.module.mes.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * MES 错误码枚举类 + *

+ * mes 系统,使用 1-040-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== MES 基础数据-物料分类(1-040-100-000) ========== + ErrorCode MD_ITEM_TYPE_NOT_EXISTS = new ErrorCode(1_040_100_000, "物料分类不存在"); + ErrorCode MD_ITEM_TYPE_EXITS_CHILDREN = new ErrorCode(1_040_100_001, "存在子分类,无法删除"); + ErrorCode MD_ITEM_TYPE_PARENT_NOT_EXITS = new ErrorCode(1_040_100_002, "父级分类不存在"); + ErrorCode MD_ITEM_TYPE_PARENT_ERROR = new ErrorCode(1_040_100_003, "不能设置自己为父分类"); + ErrorCode MD_ITEM_TYPE_NAME_DUPLICATE = new ErrorCode(1_040_100_004, "同一父分类下已存在该名称的分类"); + ErrorCode MD_ITEM_TYPE_CODE_DUPLICATE = new ErrorCode(1_040_100_005, "同一父分类下已存在该编码的分类"); + ErrorCode MD_ITEM_TYPE_PARENT_IS_CHILD = new ErrorCode(1_040_100_006, "不能设置自己的子分类为父分类"); + ErrorCode MD_ITEM_TYPE_EXITS_ITEM = new ErrorCode(1_040_100_007, "该分类下存在物料,无法删除"); + + // ========== MES 基础数据-计量单位(1-040-101-000) ========== + ErrorCode MD_UNIT_MEASURE_NOT_EXISTS = new ErrorCode(1_040_101_000, "计量单位不存在"); + ErrorCode MD_UNIT_MEASURE_CODE_DUPLICATE = new ErrorCode(1_040_101_001, "计量单位编码已存在"); + ErrorCode MD_UNIT_MEASURE_HAS_ITEM = new ErrorCode(1_040_101_002, "该计量单位下存在物料,无法删除"); + + // ========== MES 基础数据-物料(1-040-102-000) ========== + ErrorCode MD_ITEM_NOT_EXISTS = new ErrorCode(1_040_102_000, "物料不存在"); + ErrorCode MD_ITEM_CODE_DUPLICATE = new ErrorCode(1_040_102_001, "物料编码已存在"); + ErrorCode MD_ITEM_NAME_DUPLICATE = new ErrorCode(1_040_102_002, "物料名称已存在"); + ErrorCode MD_ITEM_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_102_003, "导入物料数据不能为空"); + ErrorCode MD_ITEM_BATCH_REQUIRED = new ErrorCode(1_040_102_004, "当前物料启用了批次管理,请选择批次"); + + // ========== MES 基础数据-物料批次属性配置(1-040-102-100) ========== + ErrorCode MD_ITEM_BATCH_CONFIG_NOT_EXISTS = new ErrorCode(1_040_102_100, "物料批次属性配置不存在"); + ErrorCode MD_ITEM_BATCH_CONFIG_AT_LEAST_ONE_FLAG = new ErrorCode(1_040_102_101, "批次管理已启用,至少需要配置一个批次属性"); + ErrorCode MD_ITEM_PRODUCT_BOM_REQUIRED = new ErrorCode(1_040_102_102, "产品类物料启用前,必须配置至少一个 BOM 组成"); + + // ========== MES 仓库管理-批次管理(1-040-717-000) ========== + ErrorCode WM_BATCH_PRODUCE_DATE_REQUIRED = new ErrorCode(1_040_717_000, "批次配置要求生产日期不能为空"); + ErrorCode WM_BATCH_RECEIPT_DATE_REQUIRED = new ErrorCode(1_040_717_001, "批次配置要求入库日期不能为空"); + ErrorCode WM_BATCH_EXPIRE_DATE_REQUIRED = new ErrorCode(1_040_717_002, "批次配置要求有效期不能为空"); + ErrorCode WM_BATCH_VENDOR_REQUIRED = new ErrorCode(1_040_717_003, "批次配置要求供应商不能为空"); + ErrorCode WM_BATCH_CLIENT_REQUIRED = new ErrorCode(1_040_717_004, "批次配置要求客户不能为空"); + ErrorCode WM_BATCH_PURCHASE_ORDER_CODE_REQUIRED = new ErrorCode(1_040_717_005, "批次配置要求采购订单编号不能为空"); + ErrorCode WM_BATCH_CUSTOMER_ORDER_CODE_REQUIRED = new ErrorCode(1_040_717_006, "批次配置要求销售订单编号不能为空"); + ErrorCode WM_BATCH_WORK_ORDER_REQUIRED = new ErrorCode(1_040_717_007, "批次配置要求生产工单不能为空"); + ErrorCode WM_BATCH_TASK_REQUIRED = new ErrorCode(1_040_717_008, "批次配置要求生产任务不能为空"); + ErrorCode WM_BATCH_WORKSTATION_REQUIRED = new ErrorCode(1_040_717_009, "批次配置要求工作站不能为空"); + ErrorCode WM_BATCH_TOOL_REQUIRED = new ErrorCode(1_040_717_010, "批次配置要求工具不能为空"); + ErrorCode WM_BATCH_MOLD_REQUIRED = new ErrorCode(1_040_717_011, "批次配置要求模具不能为空"); + ErrorCode WM_BATCH_LOT_NUMBER_REQUIRED = new ErrorCode(1_040_717_012, "批次配置要求生产批号不能为空"); + ErrorCode WM_BATCH_QUALITY_STATUS_REQUIRED = new ErrorCode(1_040_717_013, "批次配置要求质量状态不能为空"); + + // ========== MES 基础数据-客户(1-040-103-000) ========== + ErrorCode MD_CLIENT_NOT_EXISTS = new ErrorCode(1_040_103_000, "客户不存在"); + ErrorCode MD_CLIENT_CODE_DUPLICATE = new ErrorCode(1_040_103_001, "客户编码已存在"); + ErrorCode MD_CLIENT_NAME_DUPLICATE = new ErrorCode(1_040_103_002, "客户名称已存在"); + ErrorCode MD_CLIENT_NICKNAME_DUPLICATE = new ErrorCode(1_040_103_003, "客户简称已存在"); + ErrorCode MD_CLIENT_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_103_004, "导入客户数据不能为空"); + + // ========== MES 基础数据-供应商(1-040-104-000) ========== + ErrorCode MD_VENDOR_NOT_EXISTS = new ErrorCode(1_040_104_000, "供应商不存在"); + ErrorCode MD_VENDOR_CODE_DUPLICATE = new ErrorCode(1_040_104_001, "供应商编码已存在"); + ErrorCode MD_VENDOR_NAME_DUPLICATE = new ErrorCode(1_040_104_002, "供应商名称已存在"); + ErrorCode MD_VENDOR_NICKNAME_DUPLICATE = new ErrorCode(1_040_104_003, "供应商简称已存在"); + ErrorCode MD_VENDOR_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_104_004, "导入供应商数据不能为空"); + ErrorCode MD_VENDOR_HAS_REFERENCE = new ErrorCode(1_040_104_005, "该供应商已被其他业务引用,无法删除"); + + // ========== MES 基础数据-车间(1-040-105-000) ========== + ErrorCode MD_WORKSHOP_NOT_EXISTS = new ErrorCode(1_040_105_000, "车间不存在"); + ErrorCode MD_WORKSHOP_CODE_DUPLICATE = new ErrorCode(1_040_105_001, "车间编码已存在"); + ErrorCode MD_WORKSHOP_NAME_DUPLICATE = new ErrorCode(1_040_105_002, "车间名称已存在"); + ErrorCode MD_WORKSHOP_HAS_WORKSTATION = new ErrorCode(1_040_105_003, "车间下存在工作站,无法删除"); + + // ========== MES 基础数据-工作站(1-040-106-000) ========== + ErrorCode MD_WORKSTATION_NOT_EXISTS = new ErrorCode(1_040_106_000, "工作站不存在"); + ErrorCode MD_WORKSTATION_CODE_DUPLICATE = new ErrorCode(1_040_106_001, "工作站编码已存在"); + ErrorCode MD_WORKSTATION_NAME_DUPLICATE = new ErrorCode(1_040_106_002, "工作站名称已存在"); + // ========== MES 基础数据-设备资源(1-040-106-100) ========== + ErrorCode MD_WORKSTATION_MACHINE_NOT_EXISTS = new ErrorCode(1_040_106_100, "设备资源记录不存在"); + ErrorCode MD_WORKSTATION_MACHINE_EXISTS = new ErrorCode(1_040_106_101, "该设备已分配至工作站:{}"); + // ========== MES 基础数据-工装夹具资源(1-040-106-200) ========== + ErrorCode MD_WORKSTATION_TOOL_NOT_EXISTS = new ErrorCode(1_040_106_200, "工装夹具资源记录不存在"); + ErrorCode MD_WORKSTATION_TOOL_TYPE_EXISTS = new ErrorCode(1_040_106_201, "该工具类型已在此工作站中存在"); + // ========== MES 基础数据-人力资源(1-040-106-300) ========== + ErrorCode MD_WORKSTATION_WORKER_NOT_EXISTS = new ErrorCode(1_040_106_300, "人力资源记录不存在"); + ErrorCode MD_WORKSTATION_WORKER_POST_EXISTS = new ErrorCode(1_040_106_301, "该岗位已在此工作站中存在"); + + // ========== MES 基础数据-产品BOM(1-040-107-000) ========== + ErrorCode MD_PRODUCT_BOM_NOT_EXISTS = new ErrorCode(1_040_107_000, "产品BOM不存在"); + ErrorCode MD_PRODUCT_BOM_SELF_REFERENCE = new ErrorCode(1_040_107_001, "产品不能作为自身的BOM物料"); + ErrorCode MD_PRODUCT_BOM_CIRCULAR = new ErrorCode(1_040_107_002, "BOM物料存在闭环,无法新增"); + + // ========== MES 基础数据-产品SOP(1-040-108-000) ========== + ErrorCode MD_PRODUCT_SOP_NOT_EXISTS = new ErrorCode(1_040_108_000, "产品SOP不存在"); + ErrorCode MD_PRODUCT_SOP_SORT_DUPLICATE = new ErrorCode(1_040_108_001, "该展示序号已存在"); + + // ========== MES 基础数据-产品SIP(1-040-109-000) ========== + ErrorCode MD_PRODUCT_SIP_NOT_EXISTS = new ErrorCode(1_040_109_000, "产品SIP不存在"); + ErrorCode MD_PRODUCT_SIP_SORT_DUPLICATE = new ErrorCode(1_040_109_001, "该展示序号已存在"); + + // ========== MES 基础数据-编码规则(1-040-110-000) ========== + ErrorCode AUTO_CODE_RULE_NOT_EXISTS = new ErrorCode(1_040_110_000, "编码规则不存在"); + ErrorCode AUTO_CODE_RULE_CODE_DUPLICATE = new ErrorCode(1_040_110_001, "规则编码已存在"); + ErrorCode AUTO_CODE_PART_NOT_EXISTS = new ErrorCode(1_040_110_002, "规则组成不存在"); + ErrorCode AUTO_CODE_REDIS_ERROR = new ErrorCode(1_040_110_003, "编码生成服务不可用,请稍后重试"); + ErrorCode AUTO_CODE_GENERATE_FAILED = new ErrorCode(1_040_110_004, "编码生成失败"); + ErrorCode AUTO_CODE_PART_SERIAL_NUMBER_DUPLICATE = new ErrorCode(1_040_110_005, "流水号分段只能存在一个"); + + // ========== MES 日历排班-计划班次(1-040-200-000) ========== + ErrorCode CAL_PLAN_SHIFT_NOT_EXISTS = new ErrorCode(1_040_200_000, "计划班次不存在"); + ErrorCode CAL_PLAN_SHIFT_COUNT_EXCEED = new ErrorCode(1_040_200_001, "班次数量已达到轮班方式的上限"); + + // ========== MES 日历排班-班组(1-040-201-000) ========== + ErrorCode CAL_TEAM_NOT_EXISTS = new ErrorCode(1_040_201_000, "班组不存在"); + ErrorCode CAL_TEAM_CODE_DUPLICATE = new ErrorCode(1_040_201_001, "班组编码已存在"); + // ========== MES 日历排班-班组成员(1-040-201-100) ========== + ErrorCode CAL_TEAM_MEMBER_NOT_EXISTS = new ErrorCode(1_040_201_100, "班组成员不存在"); + ErrorCode CAL_TEAM_MEMBER_USER_DUPLICATE = new ErrorCode(1_040_201_101, "该用户已分配到其他班组"); + ErrorCode CAL_TEAM_MEMBER_USER_NOT_EXISTS = new ErrorCode(1_040_201_102, "用户不存在"); + // ========== MES 日历排班-班组排班(1-040-201-200) ========== + ErrorCode CAL_TEAM_SHIFT_NOT_EXISTS = new ErrorCode(1_040_201_200, "班组排班记录不存在"); + ErrorCode CAL_TEAM_SHIFT_GENERATE_TEAM_NOT_ENOUGH = new ErrorCode(1_040_201_201, "班组数量不满足轮班方式要求"); + ErrorCode CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH = new ErrorCode(1_040_201_202, "班次数量不满足轮班方式要求"); + + // ========== MES 日历排班-排班计划(1-040-202-000) ========== + ErrorCode CAL_PLAN_NOT_EXISTS = new ErrorCode(1_040_202_000, "排班计划不存在"); + ErrorCode CAL_PLAN_CODE_DUPLICATE = new ErrorCode(1_040_202_001, "排班计划编码已存在"); + ErrorCode CAL_PLAN_NOT_PREPARE = new ErrorCode(1_040_202_002, "排班计划已确认,不允许修改或删除"); + ErrorCode CAL_PLAN_TEAM_COUNT_NOT_MATCH = new ErrorCode(1_040_202_003, "确认排班计划时,分配的班组数量与轮班方式不匹配"); + // ========== MES 日历排班-计划班组关联(1-040-202-100) ========== + ErrorCode CAL_PLAN_TEAM_NOT_EXISTS = new ErrorCode(1_040_202_100, "计划班组关联不存在"); + ErrorCode CAL_PLAN_TEAM_DUPLICATE = new ErrorCode(1_040_202_101, "该班组已分配到此计划"); + + // ========== MES 日历排班-假期设置(1-040-203-000) ========== + ErrorCode CAL_HOLIDAY_NOT_EXISTS = new ErrorCode(1_040_203_000, "假期设置不存在"); + + // ========== MES 设备管理-设备类型(1-040-300-000) ========== + ErrorCode DV_MACHINERY_TYPE_NOT_EXISTS = new ErrorCode(1_040_300_000, "设备类型不存在"); + ErrorCode DV_MACHINERY_TYPE_EXITS_CHILDREN = new ErrorCode(1_040_300_001, "存在子类型,无法删除"); + ErrorCode DV_MACHINERY_TYPE_PARENT_NOT_EXITS = new ErrorCode(1_040_300_002, "父级类型不存在"); + ErrorCode DV_MACHINERY_TYPE_PARENT_ERROR = new ErrorCode(1_040_300_003, "不能设置自己为父类型"); + ErrorCode DV_MACHINERY_TYPE_NAME_DUPLICATE = new ErrorCode(1_040_300_004, "同一父类型下已存在该名称"); + ErrorCode DV_MACHINERY_TYPE_CODE_DUPLICATE = new ErrorCode(1_040_300_005, "设备类型编码已存在"); + ErrorCode DV_MACHINERY_TYPE_PARENT_IS_CHILD = new ErrorCode(1_040_300_006, "不能设置自己的子类型为父类型"); + ErrorCode DV_MACHINERY_TYPE_HAS_MACHINERY = new ErrorCode(1_040_300_007, "该类型下存在设备,无法删除"); + + // ========== MES 设备管理-设备台账(1-040-301-000) ========== + ErrorCode DV_MACHINERY_NOT_EXISTS = new ErrorCode(1_040_301_000, "设备不存在"); + ErrorCode DV_MACHINERY_CODE_DUPLICATE = new ErrorCode(1_040_301_001, "设备编码已存在"); + ErrorCode DV_MACHINERY_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_301_002, "导入设备数据不能为空"); + ErrorCode DV_MACHINERY_HAS_CHECK_PLAN = new ErrorCode(1_040_301_003, "设备已关联点检计划,无法删除"); + ErrorCode DV_MACHINERY_HAS_CHECK_RECORD = new ErrorCode(1_040_301_004, "设备已关联点检记录,无法删除"); + ErrorCode DV_MACHINERY_HAS_MAINTEN_RECORD = new ErrorCode(1_040_301_005, "设备已关联保养记录,无法删除"); + ErrorCode DV_MACHINERY_HAS_REPAIR = new ErrorCode(1_040_301_006, "设备已关联维修工单,无法删除"); + + // ========== MES 设备管理-点检保养项目(1-040-304-000) ========== + ErrorCode DV_SUBJECT_NOT_EXISTS = new ErrorCode(1_040_304_000, "点检保养项目不存在"); + ErrorCode DV_SUBJECT_CODE_DUPLICATE = new ErrorCode(1_040_304_001, "项目编码已存在"); + ErrorCode DV_SUBJECT_USED_BY_CHECK_PLAN = new ErrorCode(1_040_304_002, "点检保养项目已被点检保养方案使用,无法删除"); + + // ========== MES 设备管理-点检计划(1-040-302-000) ========== + ErrorCode DV_CHECK_PLAN_NOT_EXISTS = new ErrorCode(1_040_302_000, "点检计划不存在"); + ErrorCode DV_CHECK_PLAN_CODE_DUPLICATE = new ErrorCode(1_040_302_001, "点检保养方案编码已存在"); + ErrorCode DV_CHECK_PLAN_NOT_PREPARE = new ErrorCode(1_040_302_002, "点检保养方案已启用,不允许修改或删除"); + ErrorCode DV_CHECK_PLAN_NO_MACHINERY = new ErrorCode(1_040_302_003, "启用方案时,至少需要关联一台设备"); + ErrorCode DV_CHECK_PLAN_NO_SUBJECT = new ErrorCode(1_040_302_004, "启用方案时,至少需要关联一个点检保养项目"); + ErrorCode DV_CHECK_PLAN_NOT_ENABLED = new ErrorCode(1_040_302_005, "点检保养方案未启用,不允许停用"); + // ========== MES 设备管理-点检方案设备(1-040-302-100) ========== + ErrorCode DV_CHECK_PLAN_MACHINERY_NOT_EXISTS = new ErrorCode(1_040_302_100, "点检保养方案设备不存在"); + ErrorCode DV_CHECK_PLAN_MACHINERY_DUPLICATE = new ErrorCode(1_040_302_101, "该设备已关联到当前方案,请勿重复添加"); + ErrorCode DV_CHECK_PLAN_MACHINERY_EXISTS_IN_SAME_TYPE = new ErrorCode(1_040_302_102, "该设备已存在于同类型的其他启用的或草稿的方案中,不允许同一设备添加多个同类型的方案"); + // ========== MES 设备管理-点检方案项目(1-040-302-200) ========== + ErrorCode DV_CHECK_PLAN_SUBJECT_NOT_EXISTS = new ErrorCode(1_040_302_200, "点检保养方案项目不存在"); + ErrorCode DV_CHECK_PLAN_SUBJECT_DUPLICATE = new ErrorCode(1_040_302_201, "该项目已关联到当前方案,请勿重复添加"); + + // ========== MES 设备管理-维修工单(1-040-303-000) ========== + ErrorCode DV_REPAIR_NOT_EXISTS = new ErrorCode(1_040_303_000, "维修工单不存在"); + ErrorCode DV_REPAIR_NOT_PREPARE = new ErrorCode(1_040_303_001, "维修工单不是草稿状态,不允许修改或删除"); + ErrorCode DV_REPAIR_CODE_DUPLICATE = new ErrorCode(1_040_303_002, "维修工单编码已存在"); + ErrorCode DV_REPAIR_NOT_CONFIRMED = new ErrorCode(1_040_303_003, "只有维修中状态的维修工单才能完成维修"); + ErrorCode DV_REPAIR_NOT_APPROVING = new ErrorCode(1_040_303_004, "只有待验收状态的维修工单才能验收"); + // ========== MES 设备管理-维修工单行(1-040-303-100) ========== + ErrorCode DV_REPAIR_LINE_NOT_EXISTS = new ErrorCode(1_040_303_100, "维修工单行不存在"); + + // ========== MES 设备管理-保养记录(1-040-305-000) ========== + ErrorCode MAINTEN_RECORD_NOT_EXISTS = new ErrorCode(1_040_305_000, "设备保养记录不存在"); + ErrorCode MAINTEN_RECORD_NOT_DRAFT = new ErrorCode(1_040_305_001, "设备保养记录已提交,不允许修改或删除"); + ErrorCode MAINTEN_RECORD_NO_LINE = new ErrorCode(1_040_305_002, "提交保养记录时,至少需要一条保养项目"); + // ========== MES 设备管理-保养记录明细(1-040-305-100) ========== + ErrorCode MAINTEN_RECORD_LINE_NOT_EXISTS = new ErrorCode(1_040_305_100, "设备保养记录明细不存在"); + + // ========== MES 设备管理-点检记录(1-040-306-000) ========== + ErrorCode DV_CHECK_RECORD_NOT_EXISTS = new ErrorCode(1_040_306_000, "设备点检记录不存在"); + ErrorCode DV_CHECK_RECORD_NOT_DRAFT = new ErrorCode(1_040_306_001, "设备点检记录已完成,不允许修改或删除"); + ErrorCode DV_CHECK_RECORD_NO_LINE = new ErrorCode(1_040_306_002, "提交点检记录时,至少需要一条点检项目"); + // ========== MES 设备管理-点检记录明细(1-040-306-100) ========== + ErrorCode DV_CHECK_RECORD_LINE_NOT_EXISTS = new ErrorCode(1_040_306_100, "设备点检记录明细不存在"); + + // ========== MES 工具管理-工具类型(1-040-400-000) ========== + ErrorCode TM_TOOL_TYPE_NOT_EXISTS = new ErrorCode(1_040_400_000, "工具类型不存在"); + ErrorCode TM_TOOL_TYPE_CODE_DUPLICATE = new ErrorCode(1_040_400_001, "工具类型编码已存在"); + ErrorCode TM_TOOL_TYPE_NAME_DUPLICATE = new ErrorCode(1_040_400_002, "工具类型名称已存在"); + ErrorCode TM_TOOL_TYPE_HAS_TOOL = new ErrorCode(1_040_400_003, "该工具类型下存在工具,无法删除"); + + // ========== MES 工具管理-工具台账(1-040-401-000) ========== + ErrorCode TM_TOOL_NOT_EXISTS = new ErrorCode(1_040_401_000, "工具不存在"); + ErrorCode TM_TOOL_CODE_DUPLICATE = new ErrorCode(1_040_401_001, "工具编码已存在"); + + // ========== MES 生产管理-工序(1-040-500-000) ========== + ErrorCode PRO_PROCESS_NOT_EXISTS = new ErrorCode(1_040_500_000, "工序不存在"); + ErrorCode PRO_PROCESS_CODE_EXISTS = new ErrorCode(1_040_500_001, "工序编码已存在"); + ErrorCode PRO_PROCESS_NAME_EXISTS = new ErrorCode(1_040_500_002, "工序名称已存在"); + ErrorCode PRO_PROCESS_USED_BY_ROUTE = new ErrorCode(1_040_500_003, "工序已被工艺路线引用,无法删除"); + // ========== MES 生产管理-工序内容(1-040-500-100) ========== + ErrorCode PRO_PROCESS_CONTENT_NOT_EXISTS = new ErrorCode(1_040_500_100, "工序内容不存在"); + + // ========== MES 生产管理-工艺路线(1-040-501-000) ========== + ErrorCode PRO_ROUTE_NOT_EXISTS = new ErrorCode(1_040_501_000, "工艺路线不存在"); + ErrorCode PRO_ROUTE_CODE_DUPLICATE = new ErrorCode(1_040_501_001, "工艺路线编码已存在"); + ErrorCode PRO_ROUTE_ENABLE_NO_PROCESS = new ErrorCode(1_040_501_002, "请先添加组成工序"); + ErrorCode PRO_ROUTE_ENABLE_NO_KEY_PROCESS = new ErrorCode(1_040_501_003, "工艺路线必须要有关键工序"); + ErrorCode PRO_ROUTE_ENABLE_PRODUCT_NO_BOM = new ErrorCode(1_040_501_004, "产品 {} 未配置工序的 BOM 消耗"); + ErrorCode PRO_ROUTE_IS_ENABLE = new ErrorCode(1_040_501_005, "工艺路线已启用,不允许操作"); + // ========== MES 生产管理-工艺路线工序(1-040-501-100) ========== + ErrorCode PRO_ROUTE_PROCESS_NOT_EXISTS = new ErrorCode(1_040_501_100, "工艺路线工序不存在"); + ErrorCode PRO_ROUTE_PROCESS_SORT_DUPLICATE = new ErrorCode(1_040_501_101, "序号已存在"); + ErrorCode PRO_ROUTE_PROCESS_DUPLICATE = new ErrorCode(1_040_501_102, "不能重复添加工序"); + ErrorCode PRO_ROUTE_PROCESS_KEY_DUPLICATE = new ErrorCode(1_040_501_103, "当前工艺路线已经指定过关键工序"); + // ========== MES 生产管理-工艺路线产品(1-040-501-200) ========== + ErrorCode PRO_ROUTE_PRODUCT_NOT_EXISTS = new ErrorCode(1_040_501_200, "工艺路线产品不存在"); + ErrorCode PRO_ROUTE_PRODUCT_ITEM_DUPLICATE = new ErrorCode(1_040_501_201, "此产品已配置了工艺路线"); + // ========== MES 生产管理-工艺路线产品BOM(1-040-501-300) ========== + ErrorCode PRO_ROUTE_PRODUCT_BOM_NOT_EXISTS = new ErrorCode(1_040_501_300, "工艺路线产品 BOM 不存在"); + ErrorCode PRO_ROUTE_PRODUCT_BOM_DUPLICATE = new ErrorCode(1_040_501_301, "当前 BOM 物料在此工序已经配置过"); + + // ========== MES 生产管理-生产工单(1-040-502-000) ========== + ErrorCode PRO_WORK_ORDER_NOT_EXISTS = new ErrorCode(1_040_502_000, "生产工单不存在"); + ErrorCode PRO_WORK_ORDER_CODE_DUPLICATE = new ErrorCode(1_040_502_001, "生产工单编码已存在"); + ErrorCode PRO_WORK_ORDER_NOT_PREPARE = new ErrorCode(1_040_502_002, "只有草稿状态的工单才能执行此操作"); + ErrorCode PRO_WORK_ORDER_NOT_CONFIRMED = new ErrorCode(1_040_502_003, "只有已确认状态的工单才能执行此操作"); + ErrorCode PRO_WORK_ORDER_HAS_CHILDREN = new ErrorCode(1_040_502_004, "存在子工单,无法删除"); + ErrorCode PRO_WORK_ORDER_BOM_NOT_EXISTS = new ErrorCode(1_040_502_100, "生产工单BOM不存在"); + + // ========== MES 生产管理-生产任务(1-040-503-000) ========== + ErrorCode PRO_TASK_NOT_EXISTS = new ErrorCode(1_040_503_000, "生产任务不存在"); + ErrorCode PRO_TASK_ALREADY_FINISHED = new ErrorCode(1_040_503_001, "生产任务已完成或已取消,不能继续操作"); + // ========== MES 生产管理-生产任务投料(1-040-503-100) ========== + ErrorCode PRO_TASK_ISSUE_NOT_EXISTS = new ErrorCode(1_040_503_100, "生产任务投料记录不存在"); + + // ========== MES 生产管理-安灯呼叫配置(1-040-504-000) ========== + ErrorCode PRO_ANDON_CONFIG_NOT_EXISTS = new ErrorCode(1_040_504_000, "安灯呼叫配置不存在"); + + // ========== MES 生产管理-安灯呼叫记录(1-040-505-000) ========== + ErrorCode PRO_ANDON_RECORD_NOT_EXISTS = new ErrorCode(1_040_505_000, "安灯呼叫记录不存在"); + ErrorCode PRO_ANDON_RECORD_ALREADY_HANDLED = new ErrorCode(1_040_505_001, "安灯记录已处置,不允许重复处置"); + ErrorCode PRO_ANDON_RECORD_HANDLE_TIME_REQUIRED = new ErrorCode(1_040_505_002, "标记已处置时,处置时间不能为空"); + ErrorCode PRO_ANDON_RECORD_HANDLER_USER_REQUIRED = new ErrorCode(1_040_505_003, "标记已处置时,处置人不能为空"); + + // ========== MES 生产管理-生产报工(1-040-506-000) ========== + ErrorCode PRO_FEEDBACK_NOT_EXISTS = new ErrorCode(1_040_506_000, "生产报工不存在"); + ErrorCode PRO_FEEDBACK_NOT_PREPARE = new ErrorCode(1_040_506_001, "只能修改或删除草稿状态的报工单"); + ErrorCode PRO_FEEDBACK_NOT_APPROVING = new ErrorCode(1_040_506_002, "只有审批中状态的报工单才能执行此操作"); + ErrorCode PRO_FEEDBACK_NOT_UNCHECK = new ErrorCode(1_040_506_003, "只有待检验状态的报工单才能完成检验"); + ErrorCode PRO_FEEDBACK_QUANTITY_EXCEED = new ErrorCode(1_040_506_004, "报工数量不能超过排产数量"); + ErrorCode PRO_FEEDBACK_STATUS_ERROR = new ErrorCode(1_040_506_005, "报工单状态不正确,无法执行此操作"); + ErrorCode PRO_FEEDBACK_WORK_ORDER_NOT_CONFIRMED = new ErrorCode(1_040_506_006, "关联的工单未确认,无法创建报工"); + ErrorCode PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_MISMATCH = new ErrorCode(1_040_506_007, "合格品数量与不良品数量之和必须等于报工数量"); + ErrorCode PRO_FEEDBACK_ROUTE_PROCESS_INVALID = new ErrorCode(1_040_506_008, "未找到对应的工艺工序配置,请检查工艺路线与工序"); + ErrorCode PRO_FEEDBACK_TASK_OR_ORDER_FINISHED = new ErrorCode(1_040_506_009, "当前生产任务或工单已完成,不能继续报工"); + ErrorCode PRO_FEEDBACK_QUANTITY_MUST_POSITIVE = new ErrorCode(1_040_506_010, "报工数量必须大于 0"); + 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, "当前报工单未完成检验(待检数量:{}),无法执行报工"); + + // ========== MES 生产管理-生产流转卡(1-040-507-000) ========== + ErrorCode PRO_CARD_NOT_EXISTS = new ErrorCode(1_040_507_000, "生产流转卡不存在"); + ErrorCode PRO_CARD_CODE_DUPLICATE = new ErrorCode(1_040_507_001, "流转卡编码已存在"); + ErrorCode PRO_CARD_STATUS_ERROR = new ErrorCode(1_040_507_002, "流转卡状态不正确"); + ErrorCode PRO_CARD_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_507_003, "已完成或已取消的流转卡不允许取消"); + // ========== MES 生产管理-流转卡工序(1-040-507-100) ========== + ErrorCode PRO_CARD_PROCESS_NOT_EXISTS = new ErrorCode(1_040_507_100, "流转卡工序记录不存在"); + + // ========== MES 生产管理-工作记录(1-040-508-000) ========== + ErrorCode WORK_RECORD_NOT_CLOCK_IN = new ErrorCode(1_040_508_001, "当前用户未上工,无法下工"); + ErrorCode WORK_RECORD_ALREADY_CLOCK_IN = new ErrorCode(1_040_508_002, "当前用户已上工,请先下工再操作"); + + // ========== MES 质量管理-质检方案(1-040-600-000) ========== + ErrorCode QC_TEMPLATE_NOT_EXISTS = new ErrorCode(1_040_600_000, "质检方案不存在"); + ErrorCode QC_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1_040_600_001, "质检方案编号已存在"); + // ========== MES 质量管理-质检方案检测指标项(1-040-600-100) ========== + ErrorCode QC_TEMPLATE_INDICATOR_NOT_EXISTS = new ErrorCode(1_040_600_100, "质检方案检测指标项不存在"); + // ========== MES 质量管理-质检方案产品关联(1-040-600-200) ========== + ErrorCode QC_TEMPLATE_ITEM_NOT_EXISTS = new ErrorCode(1_040_600_200, "质检方案产品关联不存在"); + ErrorCode QC_TEMPLATE_ITEM_DUPLICATE = new ErrorCode(1_040_600_201, "该产品已关联此质检方案"); + + // ========== MES 质量管理-质检指标(1-040-601-000) ========== + ErrorCode QC_INDICATOR_NOT_EXISTS = new ErrorCode(1_040_601_000, "质检指标不存在"); + ErrorCode QC_INDICATOR_CODE_DUPLICATE = new ErrorCode(1_040_601_001, "质检指标编码已存在"); + ErrorCode QC_INDICATOR_NAME_DUPLICATE = new ErrorCode(1_040_601_002, "质检指标名称已存在"); + ErrorCode QC_INDICATOR_RESULT_SPECIFICATION_REQUIRED = new ErrorCode(1_040_601_003, "结果值属性不能为空"); + + // ========== MES 质量管理-缺陷类型(1-040-602-000) ========== + ErrorCode QC_DEFECT_NOT_EXISTS = new ErrorCode(1_040_602_000, "缺陷类型不存在"); + ErrorCode QC_DEFECT_CODE_DUPLICATE = new ErrorCode(1_040_602_001, "缺陷类型编码已存在"); + ErrorCode QC_DEFECT_NAME_DUPLICATE = new ErrorCode(1_040_602_002, "缺陷类型名称已存在"); + + // ========== MES 质量管理-来料检验 IQC(1-040-603-000) ========== + ErrorCode QC_IQC_NOT_EXISTS = new ErrorCode(1_040_603_000, "来料检验单不存在"); + ErrorCode QC_IQC_CODE_DUPLICATE = new ErrorCode(1_040_603_001, "来料检验单编号已存在"); + ErrorCode QC_IQC_NOT_PREPARE = new ErrorCode(1_040_603_002, "只有草稿状态的检验单才可操作"); + ErrorCode QC_IQC_QUANTITY_MISMATCH = new ErrorCode(1_040_603_004, "合格品与不合格品数量之和须等于检测数量"); + ErrorCode QC_NO_TEMPLATE = new ErrorCode(1_040_603_005, "当前产品未配置检测模板"); + ErrorCode QC_IQC_SOURCE_DOC_PARAMS_MISSING = new ErrorCode(1_040_603_006, "来源单据类型非空时,来源单据 ID 和来源单据行 ID 不能为空"); + ErrorCode QC_IQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_603_007, "完成检验单前,检测结果必须填写"); + // ========== MES 质量管理-来料检验行(1-040-603-100) ========== + ErrorCode QC_IQC_LINE_NOT_EXISTS = new ErrorCode(1_040_603_100, "来料检验行不存在"); + + // ========== MES 质量管理-过程检验 IPQC(1-040-604-000) ========== + ErrorCode QC_IPQC_NOT_EXISTS = new ErrorCode(1_040_604_000, "过程检验单不存在"); + ErrorCode QC_IPQC_CODE_DUPLICATE = new ErrorCode(1_040_604_001, "过程检验单编号已存在"); + ErrorCode QC_IPQC_NOT_PREPARE = new ErrorCode(1_040_604_002, "只有草稿状态的检验单才可操作"); + ErrorCode QC_IPQC_QUANTITY_MISMATCH = new ErrorCode(1_040_604_004, "合格品与不合格品数量之和须等于检测数量"); + ErrorCode QC_IPQC_NO_TEMPLATE = new ErrorCode(1_040_604_005, "当前产品未配置 IPQC 检测模板"); + ErrorCode QC_IPQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_604_006, "完成检验单前,检测结果必须填写"); + // ========== MES 质量管理-过程检验行(1-040-604-100) ========== + ErrorCode QC_IPQC_LINE_NOT_EXISTS = new ErrorCode(1_040_604_100, "过程检验行不存在"); + + // ========== MES 质量管理-质检缺陷记录(通用)(1-040-605-000) ========== + ErrorCode QC_DEFECT_RECORD_NOT_EXISTS = new ErrorCode(1_040_605_000, "缺陷记录不存在"); + ErrorCode QC_DEFECT_RECORD_LEVEL_UNKNOWN = new ErrorCode(1_040_605_001, "未知的缺陷等级"); + ErrorCode QC_DEFECT_RECORD_QC_TYPE_UNSUPPORTED = new ErrorCode(1_040_605_002, "不支持的检验类型"); + + // ========== MES 质量管理-检验结果(1-040-606-000) ========== + ErrorCode QC_RESULT_NOT_EXISTS = new ErrorCode(1_040_606_000, "检验结果不存在"); + + // ========== MES 质量管理-出货检验(1-040-607-000) ========== + ErrorCode QC_OQC_NOT_EXISTS = new ErrorCode(1_040_607_000, "出货检验单不存在"); + ErrorCode QC_OQC_CODE_DUPLICATE = new ErrorCode(1_040_607_001, "出货检验单编号已存在"); + ErrorCode QC_OQC_NOT_PREPARE = new ErrorCode(1_040_607_002, "只有草稿状态的检验单才可操作"); + ErrorCode QC_OQC_QUANTITY_MISMATCH = new ErrorCode(1_040_607_004, "合格品与不合格品数量之和须等于检测数量"); + ErrorCode QC_OQC_NO_TEMPLATE = new ErrorCode(1_040_607_005, "当前产品未配置 OQC 检测模板"); + ErrorCode QC_OQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_607_006, "完成检验单前,检测结果必须填写"); + // ========== MES 质量管理-出货检验行(1-040-607-100) ========== + ErrorCode QC_OQC_LINE_NOT_EXISTS = new ErrorCode(1_040_607_100, "出货检验行不存在"); + + // ========== MES 质量管理-退货检验 RQC(1-040-608-000) ========== + ErrorCode QC_RQC_NOT_EXISTS = new ErrorCode(1_040_608_000, "退货检验单不存在"); + ErrorCode QC_RQC_CODE_DUPLICATE = new ErrorCode(1_040_608_001, "退货检验单编号已存在"); + ErrorCode QC_RQC_NOT_PREPARE = new ErrorCode(1_040_608_002, "只有草稿状态的检验单才可操作"); + ErrorCode QC_RQC_QUANTITY_MISMATCH = new ErrorCode(1_040_608_004, "合格品与不合格品数量之和须等于检测数量"); + ErrorCode QC_RQC_NO_TEMPLATE = new ErrorCode(1_040_608_005, "当前产品未配置 RQC 检测模板"); + ErrorCode QC_RQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_608_006, "完成检验单前,检测结果必须填写"); + // ========== MES 质量管理-退货检验行(1-040-608-100) ========== + ErrorCode QC_RQC_LINE_NOT_EXISTS = new ErrorCode(1_040_608_100, "退货检验行不存在"); + + // ========== MES 仓库管理-仓库(1-040-700-000) ========== + ErrorCode WM_WAREHOUSE_NOT_EXISTS = new ErrorCode(1_040_700_000, "仓库不存在"); + ErrorCode WM_WAREHOUSE_CODE_DUPLICATE = new ErrorCode(1_040_700_001, "仓库编码已存在"); + ErrorCode WM_WAREHOUSE_NAME_DUPLICATE = new ErrorCode(1_040_700_002, "仓库名称已存在"); + ErrorCode WM_WAREHOUSE_HAS_LOCATION = new ErrorCode(1_040_700_003, "仓库下存在库区,无法删除"); + ErrorCode WM_WAREHOUSE_HAS_WORKSTATION = new ErrorCode(1_040_700_004, "仓库已被工作站引用,无法删除"); + ErrorCode WM_WAREHOUSE_HAS_MATERIAL_STOCK = new ErrorCode(1_040_700_005, "仓库下有库存记录,无法删除"); + ErrorCode WM_WAREHOUSE_IS_VIRTUAL = new ErrorCode(1_040_700_006, "虚拟仓库不允许操作"); + + // ========== MES 仓库管理-库区(1-040-701-000) ========== + ErrorCode WM_WAREHOUSE_LOCATION_NOT_EXISTS = new ErrorCode(1_040_701_000, "库区不存在"); + ErrorCode WM_WAREHOUSE_LOCATION_CODE_DUPLICATE = new ErrorCode(1_040_701_001, "同一仓库下库区编码已存在"); + ErrorCode WM_WAREHOUSE_LOCATION_NAME_DUPLICATE = new ErrorCode(1_040_701_002, "同一仓库下库区名称已存在"); + ErrorCode WM_WAREHOUSE_LOCATION_HAS_AREA = new ErrorCode(1_040_701_003, "库区下存在库位,无法删除"); + ErrorCode WM_WAREHOUSE_LOCATION_HAS_WORKSTATION = new ErrorCode(1_040_701_004, "库区已被工作站引用,无法删除"); + ErrorCode WM_WAREHOUSE_REQUIRED = new ErrorCode(1_040_701_005, "选择库区时,仓库不能为空"); + ErrorCode WM_WAREHOUSE_LOCATION_RELATION_INVALID = new ErrorCode(1_040_701_006, "库区不属于所选仓库"); + ErrorCode WM_WAREHOUSE_LOCATION_HAS_MATERIAL_STOCK = new ErrorCode(1_040_701_007, "库区下有库存记录,无法删除"); + ErrorCode WM_WAREHOUSE_LOCATION_IS_VIRTUAL = new ErrorCode(1_040_701_008, "虚拟库区不允许操作"); + + // ========== MES 仓库管理-库位(1-040-702-000) ========== + ErrorCode WM_WAREHOUSE_AREA_NOT_EXISTS = new ErrorCode(1_040_702_000, "库位不存在"); + ErrorCode WM_WAREHOUSE_AREA_CODE_DUPLICATE = new ErrorCode(1_040_702_001, "同一库区下库位编码已存在"); + ErrorCode WM_WAREHOUSE_AREA_NAME_DUPLICATE = new ErrorCode(1_040_702_002, "同一库区下库位名称已存在"); + ErrorCode WM_WAREHOUSE_AREA_HAS_WORKSTATION = new ErrorCode(1_040_702_003, "库位已被工作站引用,无法删除"); + ErrorCode WM_WAREHOUSE_LOCATION_REQUIRED = new ErrorCode(1_040_702_004, "选择库位时,库区不能为空"); + ErrorCode WM_WAREHOUSE_AREA_RELATION_INVALID = new ErrorCode(1_040_702_005, "库位不属于所选库区"); + ErrorCode WM_WAREHOUSE_AREA_HAS_MATERIAL_STOCK = new ErrorCode(1_040_702_006, "库位下有库存记录,无法删除"); + ErrorCode WM_WAREHOUSE_AREA_WAREHOUSE_MISMATCH = new ErrorCode(1_040_702_007, "库位不属于所选仓库"); + ErrorCode WM_WAREHOUSE_AREA_IS_VIRTUAL = new ErrorCode(1_040_702_008, "虚拟库位不允许操作"); + + // ========== MES 仓库管理-库存(1-040-703-000) ========== + ErrorCode WM_MATERIAL_STOCK_NOT_EXISTS = new ErrorCode(1_040_703_000, "库存记录不存在"); + ErrorCode WM_MATERIAL_STOCK_INSUFFICIENT = new ErrorCode(1_040_703_001, "库存数量不足"); + ErrorCode WM_TRANSACTION_TYPE_NOT_EXISTS = new ErrorCode(1_040_703_002, "库存事务类型不存在"); + ErrorCode WM_TRANSACTION_WAREHOUSE_FROZEN = new ErrorCode(1_040_703_003, "仓库({})已被冻结"); + ErrorCode WM_TRANSACTION_LOCATION_FROZEN = new ErrorCode(1_040_703_004, "库区({})已被冻结"); + ErrorCode WM_TRANSACTION_AREA_FROZEN = new ErrorCode(1_040_703_005, "库位({})已被冻结"); + ErrorCode WM_TRANSACTION_STOCK_FROZEN = new ErrorCode(1_040_703_006, "存放于({}/{}/{})下的物料已被冻结"); + ErrorCode WM_TRANSACTION_BATCH_REQUIRED = new ErrorCode(1_040_703_007, "当前物料启用了批次管理,批次号不能为空"); + ErrorCode WM_MATERIAL_STOCK_AREA_ITEM_MIXING_NOT_ALLOWED = new ErrorCode(1_040_703_008, "库位({})不允许物料混放,请选择其他库位"); + ErrorCode WM_MATERIAL_STOCK_AREA_BATCH_MIXING_NOT_ALLOWED = new ErrorCode(1_040_703_009, "库位({})不允许批次混放,请选择其他库位"); + ErrorCode WM_TRANSACTION_RELATED_NOT_EXISTS = new ErrorCode(1_040_703_010, "关联的库存事务不存在"); + ErrorCode WM_TRANSACTION_LIST_EMPTY = new ErrorCode(1_040_703_011, "库存事务列表不能为空"); + ErrorCode WM_TRANSACTION_BATCH_NOT_EXISTS = new ErrorCode(1_040_703_012, "批次记录不存在"); + + // ========== MES 仓库管理-到货通知单(1-040-704-000) ========== + ErrorCode WM_ARRIVAL_NOTICE_NOT_EXISTS = new ErrorCode(1_040_704_000, "到货通知单不存在"); + ErrorCode WM_ARRIVAL_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_704_001, "到货通知单编码已存在"); + ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE = new ErrorCode(1_040_704_002, "只有草稿状态才允许此操作"); + ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_QC = new ErrorCode(1_040_704_003, "只有待质检状态才允许审批"); + ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT = new ErrorCode(1_040_704_004, "只有待入库状态才允许完成"); + ErrorCode WM_ARRIVAL_NOTICE_IQC_PENDING = new ErrorCode(1_040_704_005, "存在待检验行,无法审批通过"); + ErrorCode WM_ARRIVAL_NOTICE_NO_LINE = new ErrorCode(1_040_704_006, "至少需要一条行项目"); + ErrorCode WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS = new ErrorCode(1_040_704_100, "到货通知单行不存在"); + ErrorCode WM_ARRIVAL_NOTICE_LINE_NOT_MATCH = new ErrorCode(1_040_704_101, "到货通知单行不属于指定的到货通知单"); + + // ========== MES 仓库管理-采购入库单(1-040-705-000) ========== + ErrorCode WM_ITEM_RECEIPT_NOT_EXISTS = new ErrorCode(1_040_705_000, "采购入库单不存在"); + ErrorCode WM_ITEM_RECEIPT_CODE_DUPLICATE = new ErrorCode(1_040_705_001, "采购入库单编码已存在"); + ErrorCode WM_ITEM_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_705_002, "只有草稿或待上架状态才允许此操作"); + ErrorCode WM_ITEM_RECEIPT_NO_LINE = new ErrorCode(1_040_705_003, "至少需要一条行项目"); + ErrorCode WM_ITEM_RECEIPT_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_705_004, "明细上架总数与行入库数量不匹配"); + ErrorCode WM_ITEM_RECEIPT_STATUS_ERROR = new ErrorCode(1_040_705_005, "入库单状态不正确"); + ErrorCode WM_ITEM_RECEIPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_705_006, "已完成或已取消的入库单不允许取消"); + ErrorCode WM_ITEM_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_705_100, "采购入库单行不存在"); + ErrorCode WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_REQUIRED = new ErrorCode(1_040_705_101, + "入库单关联了到货通知单,必须选择到货通知单行"); + ErrorCode WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_NOT_ALLOWED = new ErrorCode(1_040_705_102, + "入库单未关联到货通知单,不能选择到货通知单行"); + ErrorCode WM_ITEM_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_705_200, "采购入库明细不存在"); + ErrorCode WM_ITEM_RECEIPT_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_705_202, "上架明细总数量不能超过行入库数量"); + + // ========== MES 仓库管理-领料申请单(1-040-706-000) ========== + ErrorCode WM_MATERIAL_REQUEST_NOT_EXISTS = new ErrorCode(1_040_706_000, "领料申请单不存在"); + ErrorCode WM_MATERIAL_REQUEST_STATUS_INVALID = new ErrorCode(1_040_706_001, "领料申请单状态不正确,无法执行该操作"); + ErrorCode WM_MATERIAL_REQUEST_LINE_NOT_EXISTS = new ErrorCode(1_040_706_100, "领料申请单行不存在"); + + // ========== MES 仓库管理-外协发料单(1-040-707-000) ========== + ErrorCode WM_OUTSOURCE_ISSUE_NOT_EXISTS = new ErrorCode(1_040_707_000, "外协发料单不存在"); + ErrorCode WM_OUTSOURCE_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_707_001, "外协发料单编码已存在"); + ErrorCode WM_OUTSOURCE_ISSUE_STATUS_NOT_PREPARE = new ErrorCode(1_040_707_002, "只有草稿状态才允许此操作"); + ErrorCode WM_OUTSOURCE_ISSUE_NO_LINE = new ErrorCode(1_040_707_003, "至少需要一条发料行"); + ErrorCode WM_OUTSOURCE_ISSUE_QUANTITY_MISMATCH = new ErrorCode(1_040_707_004, "发料单行数量与明细数量不一致"); + ErrorCode WM_OUTSOURCE_ISSUE_STATUS_NOT_APPROVING = new ErrorCode(1_040_707_005, "只有待拣货状态才允许此操作"); + ErrorCode WM_OUTSOURCE_ISSUE_STATUS_NOT_APPROVED = new ErrorCode(1_040_707_006, "只有待执行出库状态才允许此操作"); + ErrorCode WM_OUTSOURCE_ISSUE_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_707_007, "已完成或已取消的发料单不允许取消"); + ErrorCode WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_707_100, "外协发料单行不存在"); + ErrorCode WM_OUTSOURCE_ISSUE_LINE_ITEM_NOT_IN_BOM = new ErrorCode(1_040_707_101, "发料单行对应的物料不在当前工单的 BOM 列表中"); + ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_707_200, "外协发料单明细不存在"); + ErrorCode WM_OUTSOURCE_ISSUE_WORK_ORDER_TYPE_INVALID = new ErrorCode(1_040_707_008, "工单类型不是外协(代工)类型"); + + // ========== MES 仓库管理-生产领料出库单(1-040-708-000) ========== + ErrorCode WM_PRODUCT_ISSUE_NOT_EXISTS = new ErrorCode(1_040_708_000, "生产领料出库单不存在"); + ErrorCode WM_PRODUCT_ISSUE_STATUS_INVALID = new ErrorCode(1_040_708_001, "生产领料出库单状态不正确,无法执行该操作"); + ErrorCode WM_PRODUCT_ISSUE_NO_LINE = new ErrorCode(1_040_708_002, "生产领料出库单至少需要一条行数据"); + ErrorCode WM_PRODUCT_ISSUE_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_708_003, "领料出库单行数量与明细数量不一致"); + ErrorCode WM_PRODUCT_ISSUE_WORKORDER_NOT_EXISTS = new ErrorCode(1_040_708_004, "生产工单不存在"); + ErrorCode WM_PRODUCT_ISSUE_WORKSTATION_NOT_EXISTS = new ErrorCode(1_040_708_005, "工作站不存在"); + ErrorCode WM_PRODUCT_ISSUE_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_708_006, "生产领料出库单已完成或已取消,无法取消"); + ErrorCode WM_PRODUCT_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_708_100, "生产领料出库单行不存在"); + ErrorCode WM_PRODUCT_ISSUE_LINE_ITEM_NOT_IN_BOM = new ErrorCode(1_040_708_101, "当前物料不在生产工单的 BOM 物料清单中"); + ErrorCode WM_PRODUCT_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_708_102, "领料出库单编码已存在"); + ErrorCode WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_708_200, "生产领料出库单明细不存在"); + ErrorCode WM_PRODUCT_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_708_201, "拣货明细的物料与领料单行的物料不一致"); + + // ========== MES 仓库管理-生产入库单(1-040-709-000) ========== + ErrorCode WM_PRODUCT_PRODUCE_NOT_EXISTS = new ErrorCode(1_040_709_000, "生产入库单不存在"); + ErrorCode WM_PRODUCT_PRODUCE_STATUS_INVALID = new ErrorCode(1_040_709_001, "生产入库单状态不正确,无法执行该操作"); + ErrorCode WM_PRODUCT_PRODUCE_NO_LINE = new ErrorCode(1_040_709_002, "生产入库单至少需要一条行数据"); + ErrorCode WM_PRODUCT_PRODUCE_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_709_003, "生产入库单行数量与明细数量不一致"); + ErrorCode WM_PRODUCT_PRODUCE_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_709_004, "生产入库单已完成或已取消,无法取消"); + ErrorCode WM_PRODUCT_PRODUCE_LINE_NOT_EXISTS = new ErrorCode(1_040_709_100, "生产入库单行不存在"); + ErrorCode WM_PRODUCT_PRODUCE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_709_200, "生产入库单明细不存在"); + + // ========== MES 仓库管理-转移调拨(1-040-710-000) ========== + ErrorCode WM_TRANSFER_NOT_EXISTS = new ErrorCode(1_040_710_000, "转移单不存在"); + ErrorCode WM_TRANSFER_NOT_EDITABLE = new ErrorCode(1_040_710_001, "当前转移单状态不允许编辑"); + ErrorCode WM_TRANSFER_CODE_DUPLICATE = new ErrorCode(1_040_710_002, "转移单编号已存在"); + ErrorCode WM_TRANSFER_NOT_DRAFT = new ErrorCode(1_040_710_003, "只有草稿状态的转移单才可操作"); + ErrorCode WM_TRANSFER_NOT_CONFIRMED = new ErrorCode(1_040_710_004, "只有待确认状态的转移单才可执行确认"); + ErrorCode WM_TRANSFER_NOT_APPROVING = new ErrorCode(1_040_710_005, "只有待上架状态的转移单才可执行上架"); + ErrorCode WM_TRANSFER_NOT_APPROVED = new ErrorCode(1_040_710_006, "只有待执行状态的转移单才可完成"); + ErrorCode WM_TRANSFER_ALREADY_FINISHED = new ErrorCode(1_040_710_007, "转移单已完成或已取消,无法继续操作"); + ErrorCode WM_TRANSFER_NO_LINE = new ErrorCode(1_040_710_008, "转移单至少需要一条行数据"); + ErrorCode WM_TRANSFER_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_710_009, "转移单行数量与明细数量不一致"); + ErrorCode WM_TRANSFER_LINE_NOT_EXISTS = new ErrorCode(1_040_710_100, "转移单行不存在"); + ErrorCode WM_TRANSFER_LINE_QUANTITY_EXCEED_STOCK = new ErrorCode(1_040_710_101, "转移数量不能超过库存数量"); + ErrorCode WM_TRANSFER_DETAIL_NOT_EXISTS = new ErrorCode(1_040_710_200, "调拨明细不存在"); + ErrorCode WM_TRANSFER_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_710_201, "调拨明细总数量不能超过调拨单行数量"); + ErrorCode WM_TRANSFER_DETAIL_MIXED_GOODS = new ErrorCode(1_040_710_202, "同一目标仓位下已存在其他物料的明细,不允许混货"); + + // ========== MES 仓库管理-生产退料单(1-040-711-000) ========== + ErrorCode WM_RETURN_ISSUE_NOT_EXISTS = new ErrorCode(1_040_710_000, "生产退料单不存在"); + ErrorCode WM_RETURN_ISSUE_STATUS_INVALID = new ErrorCode(1_040_710_001, "生产退料单状态不正确,无法执行该操作"); + ErrorCode WM_RETURN_ISSUE_NOT_PREPARE = new ErrorCode(1_040_710_002, "只有草稿状态的退料单才可操作"); + ErrorCode WM_RETURN_ISSUE_NOT_CONFIRMED = new ErrorCode(1_040_710_003, "只有待检验状态的退料单才可提交"); + ErrorCode WM_RETURN_ISSUE_NOT_APPROVING = new ErrorCode(1_040_710_004, "只有待上架状态的退料单才可入库上架"); + ErrorCode WM_RETURN_ISSUE_NOT_APPROVED = new ErrorCode(1_040_710_005, "只有待执行退料状态的退料单才可完成"); + ErrorCode WM_RETURN_ISSUE_NO_LINE = new ErrorCode(1_040_710_006, "生产退料单至少需要一条行数据"); + ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_710_007, "退料单行数量与明细数量不一致"); + ErrorCode WM_RETURN_ISSUE_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_710_008, "生产退料单已完成或已取消,无法取消"); + ErrorCode WM_RETURN_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_710_100, "生产退料单行不存在"); + ErrorCode WM_RETURN_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_710_200, "生产退料单明细不存在"); + ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_710_201, "退料明细数量必须大于0"); + ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_710_202, "退料明细总数量不能超过退料单行数量"); + ErrorCode WM_RETURN_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_710_203, "退料单编码已存在"); + + // ========== MES 仓库管理-供应商退货单(1-040-711-000) ========== + ErrorCode WM_RETURN_VENDOR_NOT_EXISTS = new ErrorCode(1_040_711_000, "供应商退货单不存在"); + ErrorCode WM_RETURN_VENDOR_STATUS_INVALID = new ErrorCode(1_040_711_001, "供应商退货单状态不正确,无法执行该操作"); + ErrorCode WM_RETURN_VENDOR_NO_LINE = new ErrorCode(1_040_711_002, "供应商退货单至少需要一条行数据"); + ErrorCode WM_RETURN_VENDOR_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_711_003, "供应商退货单行数量与明细数量不一致"); + ErrorCode WM_RETURN_VENDOR_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_711_004, "供应商退货单已完成或已取消,无法取消"); + ErrorCode WM_RETURN_VENDOR_CODE_DUPLICATE = new ErrorCode(1_040_711_005, "供应商退货单编号已存在"); + ErrorCode WM_RETURN_VENDOR_NO_DETAIL = new ErrorCode(1_040_711_006, "供应商退货单没有拣货明细,无法执行退货"); + ErrorCode WM_RETURN_VENDOR_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_711_007, "拣货明细的物料与退货单行的物料不一致"); + ErrorCode WM_RETURN_VENDOR_LINE_NOT_EXISTS = new ErrorCode(1_040_711_100, "供应商退货单行不存在"); + ErrorCode WM_RETURN_VENDOR_DETAIL_NOT_EXISTS = new ErrorCode(1_040_711_200, "供应商退货单明细不存在"); + ErrorCode WM_RETURN_VENDOR_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_711_201, "退货明细数量必须大于 0"); + + // ========== MES 仓库管理-产品收货单(1-040-712-000) ========== + ErrorCode WM_PRODUCT_RECPT_NOT_EXISTS = new ErrorCode(1_040_712_000, "产品收货单不存在"); + ErrorCode WM_PRODUCT_RECPT_CODE_DUPLICATE = new ErrorCode(1_040_712_001, "产品收货单编码已存在"); + ErrorCode WM_PRODUCT_RECPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_712_002, "只有草稿或待上架状态才允许此操作"); + ErrorCode WM_PRODUCT_RECPT_NO_LINE = new ErrorCode(1_040_712_003, "至少需要一条行项目"); + ErrorCode WM_PRODUCT_RECPT_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_712_004, "明细上架总数与行收货数量不匹配"); + ErrorCode WM_PRODUCT_RECPT_STATUS_ERROR = new ErrorCode(1_040_712_005, "收货单状态不正确"); + ErrorCode WM_PRODUCT_RECPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_712_006, "已完成或已取消的收货单不允许取消"); + ErrorCode WM_PRODUCT_RECPT_NO_DETAIL = new ErrorCode(1_040_712_007, "收货单没有上架明细,无法执行入库"); + ErrorCode WM_PRODUCT_RECPT_LINE_NOT_EXISTS = new ErrorCode(1_040_712_100, "产品收货单行不存在"); + ErrorCode WM_PRODUCT_RECPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_712_200, "产品收货明细不存在"); + + // ========== MES 仓库管理-外协入库单(1-040-713-000) ========== + ErrorCode WM_OUTSOURCE_RECEIPT_NOT_EXISTS = new ErrorCode(1_040_713_000, "外协入库单不存在"); + ErrorCode WM_OUTSOURCE_RECEIPT_CODE_DUPLICATE = new ErrorCode(1_040_713_001, "外协入库单编码已存在"); + ErrorCode WM_OUTSOURCE_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_713_002, "只有草稿状态才允许此操作"); + ErrorCode WM_OUTSOURCE_RECEIPT_NO_LINE = new ErrorCode(1_040_713_003, "至少需要一条行项目"); + ErrorCode WM_OUTSOURCE_RECEIPT_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_713_004, "明细上架总数与行入库数量不匹配"); + ErrorCode WM_OUTSOURCE_RECEIPT_STATUS_ERROR = new ErrorCode(1_040_713_005, "入库单状态不正确"); + ErrorCode WM_OUTSOURCE_RECEIPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_713_006, "已完成或已取消的入库单不允许取消"); + ErrorCode WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_713_100, "外协入库单行不存在"); + ErrorCode WM_OUTSOURCE_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_713_200, "外协入库明细不存在"); + + // ========== MES 仓库管理-销售退货单(1-040-713-000) ========== + ErrorCode WM_RETURN_SALES_NOT_EXISTS = new ErrorCode(1_040_713_000, "销售退货单不存在"); + ErrorCode WM_RETURN_SALES_CODE_DUPLICATE = new ErrorCode(1_040_713_001, "销售退货单编码已存在"); + ErrorCode WM_RETURN_SALES_STATUS_NOT_PREPARE = new ErrorCode(1_040_713_002, "只有草稿状态才允许此操作"); + ErrorCode WM_RETURN_SALES_STATUS_NOT_APPROVING = new ErrorCode(1_040_713_003, "只有待执行状态才允许执行退货"); + ErrorCode WM_RETURN_SALES_STATUS_NOT_APPROVED = new ErrorCode(1_040_713_004, "只有待上架状态才允许执行上架"); + ErrorCode WM_RETURN_SALES_NO_LINE = new ErrorCode(1_040_713_005, "销售退货单至少需要一条行数据"); + ErrorCode WM_RETURN_SALES_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_713_006, "销售退货单行数量与明细数量不一致"); + ErrorCode WM_RETURN_SALES_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_713_007, "销售退货单已完成或已取消,无法取消"); + ErrorCode WM_RETURN_SALES_LINE_NOT_EXISTS = new ErrorCode(1_040_713_100, "销售退货单行不存在"); + ErrorCode WM_RETURN_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_713_200, "销售退货单明细不存在"); + ErrorCode WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_713_201, "上架明细总数量不能超过退货行数量"); + + // ========== MES 仓库管理-盘点方案/任务/结果(1-040-714-100) ========== + ErrorCode WM_STOCK_TAKING_PLAN_NOT_EXISTS = new ErrorCode(1_040_714_100, "盘点方案不存在"); + ErrorCode WM_STOCK_TAKING_PLAN_CODE_DUPLICATE = new ErrorCode(1_040_714_101, "盘点方案编码已存在"); + ErrorCode WM_STOCK_TAKING_PLAN_NOT_DISABLED = new ErrorCode(1_040_714_102, "只有禁用状态的盘点方案才允许修改、删除或维护参数"); + ErrorCode WM_STOCK_TAKING_PLAN_NOT_ENABLED = new ErrorCode(1_040_714_103, "只有启用状态的盘点方案才允许生成任务"); + ErrorCode WM_STOCK_TAKING_PLAN_PARAM_NOT_EXISTS = new ErrorCode(1_040_714_104, "盘点方案参数不存在"); + ErrorCode WM_STOCK_TAKING_PLAN_PARAM_EMPTY = new ErrorCode(1_040_714_105, "盘点方案参数不能为空,请先配置盘点参数"); + ErrorCode WM_STOCK_TAKING_PLAN_DYNAMIC_TIME_INVALID = new ErrorCode(1_040_714_106, "动态盘点方案必须设置开始时间和结束时间,且结束时间必须晚于开始时间"); + ErrorCode WM_STOCK_TAKING_TASK_NOT_EXISTS = new ErrorCode(1_040_714_110, "盘点任务不存在"); + ErrorCode WM_STOCK_TAKING_TASK_CODE_DUPLICATE = new ErrorCode(1_040_714_111, "盘点任务编码已存在"); + ErrorCode WM_STOCK_TAKING_TASK_NOT_PREPARE = new ErrorCode(1_040_714_112, "只有草稿状态的盘点任务才允许此操作"); + ErrorCode WM_STOCK_TAKING_TASK_NOT_APPROVING = new ErrorCode(1_040_714_113, "只有盘点中状态的任务才允许此操作"); + ErrorCode WM_STOCK_TAKING_TASK_CANNOT_CANCEL = new ErrorCode(1_040_714_114, "已完成或已取消的盘点任务不允许取消"); + ErrorCode WM_STOCK_TAKING_TASK_NO_STOCK = new ErrorCode(1_040_714_115, "未找到符合条件的库存数据"); + ErrorCode WM_STOCK_TAKING_TASK_NO_LINE = new ErrorCode(1_040_714_116, "盘点任务至少需要一条任务行"); + ErrorCode WM_STOCK_TAKING_TASK_LINE_NOT_EXISTS = new ErrorCode(1_040_714_117, "盘点任务行不存在"); + ErrorCode WM_STOCK_TAKING_TASK_DYNAMIC_TIME_REQUIRED = new ErrorCode(1_040_714_118, "动态盘点必须选择开始时间和结束时间"); + ErrorCode WM_STOCK_TAKING_TASK_RESULT_NOT_EXISTS = new ErrorCode(1_040_714_119, "盘点结果不存在"); + ErrorCode WM_STOCK_TAKING_TASK_LINE_ALREADY_TAKEN = new ErrorCode(1_040_714_120, "该盘点清单行已有盘点记录,不能重复盘点"); + + // ========== MES 仓库管理-销售出库单(1-040-714-000) ========== + ErrorCode WM_PRODUCT_SALES_NOT_EXISTS = new ErrorCode(1_040_714_000, "销售出库单不存在"); + ErrorCode WM_PRODUCT_SALES_CODE_DUPLICATE = new ErrorCode(1_040_714_001, "销售出库单号已存在"); + ErrorCode WM_PRODUCT_SALES_NOT_PREPARE = new ErrorCode(1_040_714_002, "只有草稿状态才可操作"); + ErrorCode WM_PRODUCT_SALES_LINES_EMPTY = new ErrorCode(1_040_714_003, "销售出库单行不能为空"); + ErrorCode WM_PRODUCT_SALES_CANNOT_SUBMIT = new ErrorCode(1_040_714_004, "当前状态不允许提交"); + ErrorCode WM_PRODUCT_SALES_CANNOT_PICK = new ErrorCode(1_040_714_005, "当前状态不允许拣货"); + ErrorCode WM_PRODUCT_SALES_CANNOT_SHIPPING = new ErrorCode(1_040_714_006, "当前状态不允许填写运单"); + ErrorCode WM_PRODUCT_SALES_CANNOT_FINISH = new ErrorCode(1_040_714_007, "当前状态不允许执行出库"); + ErrorCode WM_PRODUCT_SALES_CANNOT_CANCEL = new ErrorCode(1_040_714_008, "当前状态不允许取消"); + ErrorCode WM_PRODUCT_SALES_CANNOT_CONFIRM = new ErrorCode(1_040_714_009, "当前状态不允许确认检验通过"); + ErrorCode WM_PRODUCT_SALES_DETAILS_EMPTY = new ErrorCode(1_040_714_020, "拣货明细不能为空"); + ErrorCode WM_PRODUCT_SALES_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_714_010, "拣货数量与出库数量不匹配"); + ErrorCode WM_PRODUCT_SALES_LINE_NOT_EXISTS = new ErrorCode(1_040_714_011, "销售出库单行不存在"); + ErrorCode WM_PRODUCT_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_714_012, "销售出库明细不存在"); + ErrorCode WM_PRODUCT_SALES_STOCK_INSUFFICIENT = new ErrorCode(1_040_714_013, "库存不足,无法拣货"); + ErrorCode WM_PRODUCT_SALES_LINE_QUANTITY_INVALID = new ErrorCode(1_040_714_014, "出库数量必须大于 0"); + + // ========== MES 仓库管理-杂项出库单(1-040-715-000) ========== + ErrorCode WM_MISC_ISSUE_NOT_EXISTS = new ErrorCode(1_040_715_000, "杂项出库单不存在"); + ErrorCode WM_MISC_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_715_001, "杂项出库单编码已存在"); + ErrorCode WM_MISC_ISSUE_STATUS_INVALID = new ErrorCode(1_040_715_002, "杂项出库单状态不正确,无法执行该操作"); + ErrorCode WM_MISC_ISSUE_NO_LINE = new ErrorCode(1_040_715_003, "杂项出库单至少需要一条行数据"); + ErrorCode WM_MISC_ISSUE_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_715_004, "杂项出库单已完成或已取消,无法取消"); + ErrorCode WM_MISC_ISSUE_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_715_005, "杂项出库单行数量与明细数量不一致"); + ErrorCode WM_MISC_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_715_100, "杂项出库单行不存在"); + ErrorCode WM_MISC_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_715_200, "杂项出库单明细不存在"); + + // ========== MES 仓库管理-杂项入库单(1-040-716-000) ========== + ErrorCode WM_MISC_RECEIPT_NOT_EXISTS = new ErrorCode(1_040_716_000, "杂项入库单不存在"); + ErrorCode WM_MISC_RECEIPT_CODE_DUPLICATE = new ErrorCode(1_040_716_001, "杂项入库单编码已存在"); + ErrorCode WM_MISC_RECEIPT_STATUS_NOT_PREPARE = new ErrorCode(1_040_716_002, "只有草稿状态才允许此操作"); + ErrorCode WM_MISC_RECEIPT_STATUS_NOT_APPROVED = new ErrorCode(1_040_716_003, "只有已审批状态才允许执行入库"); + ErrorCode WM_MISC_RECEIPT_NO_LINE = new ErrorCode(1_040_716_004, "至少需要一条行项目"); + ErrorCode WM_MISC_RECEIPT_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_716_005, "已完成或已取消的入库单不允许取消"); + ErrorCode WM_MISC_RECEIPT_LINE_NOT_EXISTS = new ErrorCode(1_040_716_100, "杂项入库单行不存在"); + ErrorCode WM_MISC_RECEIPT_WAREHOUSE_REQUIRED = new ErrorCode(1_040_716_101, "仓库不能为空"); + ErrorCode WM_MISC_RECEIPT_QUANTITY_INVALID = new ErrorCode(1_040_716_102, "入库数量必须大于 0"); + ErrorCode WM_MISC_RECEIPT_DETAIL_NOT_EXISTS = new ErrorCode(1_040_716_200, "杂项入库单明细不存在"); + + // ========== MES 仓库管理-发货通知单(1-040-720-000) ========== + ErrorCode WM_SALES_NOTICE_NOT_EXISTS = new ErrorCode(1_040_720_000, "发货通知单不存在"); + ErrorCode WM_SALES_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_720_001, "通知单编号重复"); + ErrorCode WM_SALES_NOTICE_STATUS_NOT_ALLOW_DELETE = new ErrorCode(1_040_720_002, "单据状态不允许删除"); + ErrorCode WM_SALES_NOTICE_STATUS_NOT_ALLOW_UPDATE = new ErrorCode(1_040_720_003, "单据状态不允许修改"); + ErrorCode WM_SALES_NOTICE_LINE_NOT_EXISTS = new ErrorCode(1_040_720_010, "发货通知单行不存在"); + ErrorCode WM_SALES_NOTICE_LINE_EMPTY = new ErrorCode(1_040_720_011, "发货通知单行为空,不能提交"); + + // ========== MES 仓库管理-条码配置(1-040-730-000) ========== + ErrorCode WM_BARCODE_CONFIG_NOT_EXISTS = new ErrorCode(1_040_730_000, "条码配置不存在"); + ErrorCode WM_BARCODE_CONFIG_BIZ_TYPE_DUPLICATE = new ErrorCode(1_040_730_001, "该业务类型的条码配置已存在"); + ErrorCode WM_BARCODE_CONFIG_HAS_BARCODE = new ErrorCode(1_040_730_002, "该条码配置已被条码记录关联,无法删除"); + + // ========== MES 仓库管理-条码清单(1-040-731-000) ========== + ErrorCode WM_BARCODE_NOT_EXISTS = new ErrorCode(1_040_731_000, "条码不存在"); + ErrorCode WM_BARCODE_ALREADY_EXISTS = new ErrorCode(1_040_731_001, "该业务对象的条码已存在"); + ErrorCode WM_BARCODE_CONTENT_DUPLICATE = new ErrorCode(1_040_731_002, "条码内容已存在"); + ErrorCode BARCODE_BIZ_TYPE_NOT_EXISTS = new ErrorCode(1_040_731_003, "业务类型不能为空"); + ErrorCode BARCODE_BIZ_CODE_NOT_EXISTS = new ErrorCode(1_040_731_004, "业务编码不能为空"); + ErrorCode BARCODE_CONFIG_NOT_EXISTS = new ErrorCode(1_040_731_005, "条码配置不存在"); + + // ========== MES 仓库管理-装箱单(1-040-740-000) ========== + ErrorCode WM_PACKAGE_NOT_EXISTS = new ErrorCode(1_040_740_000, "装箱单不存在"); + ErrorCode WM_PACKAGE_CODE_DUPLICATE = new ErrorCode(1_040_740_001, "装箱单编码已存在"); + ErrorCode WM_PACKAGE_STATUS_NOT_PREPARE = new ErrorCode(1_040_740_002, "只有草稿状态才允许此操作"); + ErrorCode WM_PACKAGE_PARENT_NOT_EXISTS = new ErrorCode(1_040_740_003, "父箱不存在"); + ErrorCode WM_PACKAGE_PARENT_SELF = new ErrorCode(1_040_740_004, "不能选择自己作为父箱"); + ErrorCode WM_PACKAGE_CHILD_HAS_PARENT = new ErrorCode(1_040_740_005, "该装箱单已有父箱,不能重复添加"); + ErrorCode WM_PACKAGE_PARENT_IS_CHILD = new ErrorCode(1_040_740_006, "不能选择子箱的后代作为父箱,会形成环路"); + ErrorCode WM_PACKAGE_CHILD_NOT_FINISHED = new ErrorCode(1_040_740_007, "子箱必须是已完成状态才能添加"); + ErrorCode WM_PACKAGE_HAS_CHILDREN = new ErrorCode(1_040_740_008, "存在子箱,不允许删除"); + ErrorCode WM_PACKAGE_LINE_NOT_EXISTS = new ErrorCode(1_040_740_100, "装箱明细不存在"); + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/MesBizTypeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/MesBizTypeConstants.java new file mode 100644 index 000000000..2bef47c2e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/MesBizTypeConstants.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.mes.enums; + +/** + * MES 业务类型常量 + * + * 集中管理业务类型枚举的编号,按业务域分段。 + * 各枚举类引用此处常量,避免硬编码数字。(也避免冲突!!!) + * + * @author 芋道源码 + */ +public final class MesBizTypeConstants { + + private MesBizTypeConstants() {} + + // ========== QC 质检模块 [1, 100) ========== + + public static final int QC_IQC = 1; // 来料检验:MesQcIqcDO + public static final int QC_IPQC = 2; // 过程检验:MesQcIpqcDO + public static final int QC_OQC = 3; // 出货检验:MesQcOqcDO + public static final int QC_RQC = 4; // 退货检验:MesQcRqcDO + + // ========== WM 仓库模块 [100, 200) ========== + + public static final int WM_ARRIVAL_NOTICE = 100; // 到货通知单:MesWmArrivalNoticeDO + public static final int WM_WAREHOUSE = 102; // 仓库:MesWmWarehouseDO + public static final int WM_LOCATION = 103; // 库位:MesWmLocationDO + public static final int WM_AREA = 104; // 库位:MesWmStorageAreaDO + public static final int WM_PACKAGE = 105; // 装箱单:MesWmPackageDO + public static final int WM_STOCK = 106; // 库存:MesWmMaterialStockDO + public static final int WM_BATCH = 107; // 批次:MesWmBatchDO + public static final int WM_TRANSACTION = 108; // 库存事务流水:MesWmTransactionDO + public static final int WM_ITEM_RECEIPT_IN = 110; // 采购入库:MesWmItemReceiptDO + public static final int WM_TRANSFER_OUT = 111; // 调拨出库:MesWmTransferDO + public static final int WM_TRANSFER_IN = 112; // 调拨入库:MesWmTransferDO + public static final int WM_MISC_ISSUE = 113; // 其他出库:MesWmMiscIssueDO + public static final int WM_MISC_RECPT = 114; // 其他入库:MesWmMiscReceiptDO + public static final int WM_ISSUE = 115; // 生产领料:MesWmProductIssueDO + public static final int WM_RETURN_ISSUE = 116; // 生产退料:MesWmReturnIssueDO + public static final int WM_PRODUCT_RECPT = 117; // 生产入库:MesWmProductReceiptDO + public static final int WM_PRODUCT_SALES = 118; // 销售出库:MesWmProductSalesDO + public static final int WM_RETURN_SALES = 119; // 销售退货入库:MesWmReturnSalesDO + public static final int WM_OUTSOURCE_ISSUE = 120; // 外协发料:MesWmOutsourceIssueDO + public static final int WM_OUTSOURCE_RECPT = 121; // 外协入库:MesWmOutsourceReceiptDO + public static final int WM_ITEM_CONSUME = 122; // 生产消耗:MesWmItemConsumeDO + public static final int WM_PRODUCT_PRODUCE = 123; // 产品产出:MesWmProductProduceDO + public static final int WM_RETURN_VENDOR = 124; // 供应商退货出库:MesWmReturnVendorDO + + // ========== CAL 排班模块 [200, 300) ========== + + // TODO @芋艿【暂时忽略】:MesProWorkOrderTypeEnum + // TODO @芋艿【暂时忽略】:MesProWorkOrderSourceTypeEnum + + // ========== PRO 生产模块 [300, 400) ========== + + public static final int PRO_CARD = 300; // 流转卡:MesProCardDO + public static final int PRO_WORKORDER = 301; // 工单:MesProWorkOrderDO + public static final int PRO_TRANS_ORDER = 302; // 流转单:MesProTransOrderDO + public static final int PRO_TASK = 303; // 生产任务:MesProTaskDO + public static final int PRO_FEEDBACK = 304; // 生产报工:MesProFeedbackDO + + // ========== DV 设备模块 [400, 500) ========== + + public static final int DV_MACHINERY = 400; // 设备:MesDvMachineryDO + + // ========== TM 工装夹具模块 [500, 600) ========== + + public static final int TM_TOOL = 500; // 工装:MesToolDO + + // ========== MD 主数据模块 [600, 700) ========== + + public static final int MD_ITEM = 600; // 物料:MesMdItemDO + public static final int MD_VENDOR = 601; // 供应商:MesMdVendorDO + public static final int MD_WORKSTATION = 602; // 工作站:MesMdWorkstationDO + public static final int MD_WORKSHOP = 603; // 车间:MesMdWorkshopDO + public static final int MD_USER = 604; // 人员:系统用户 + public static final int MD_CLIENT = 605; // 客户:MesMdClientDO + + // ========== 特殊类型(非业务实体) [900, 1000) ========== + + public static final int QUALITY_STATUS = 900; // 质量状态:非实体,用于盘点等场景的状态筛选 + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/MesOrderStatusConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/MesOrderStatusConstants.java new file mode 100644 index 000000000..de5a9ab0e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/MesOrderStatusConstants.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.enums; + +/** + * MES 单据状态常量 + * + * 集中管理各模块单据状态的编号,作为状态值的中央注册中心。 + * 各枚举类引用此处常量,避免硬编码数字。 + * + * @author 芋道源码 + */ +public final class MesOrderStatusConstants { + + /** + * 草稿 + */ + public static final int PREPARE = 0; + + /** + * 已确认 + */ + public static final int CONFIRMED = 1; + /** + * 审批中 + */ + public static final int APPROVING = 2; + /** + * 已审批 + */ + public static final int APPROVED = 3; + + /** + * 已完成 + */ + public static final int FINISHED = 4; + /** + * 已取消 + */ + public static final int CANCELLED = 5; + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalHolidayTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalHolidayTypeEnum.java new file mode 100644 index 000000000..027350a33 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalHolidayTypeEnum.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.enums.cal; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 假期类型枚举 + * + * 对应字典 mes_cal_holiday_type + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesCalHolidayTypeEnum implements ArrayValuable { + + WORKDAY(1, "工作日"), + HOLIDAY(2, "节假日"); + + public static final Integer[] ARRAYS = Arrays.stream(values()) + .map(MesCalHolidayTypeEnum::getType).toArray(Integer[]::new); + + private final Integer type; + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalPlanStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalPlanStatusEnum.java new file mode 100644 index 000000000..c4cb84a85 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalPlanStatusEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.cal; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 排班计划状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesCalPlanStatusEnum implements ArrayValuable { + + PREPARE(0, "草稿"), + CONFIRMED(1, "已确认"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesCalPlanStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftMethodEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftMethodEnum.java new file mode 100644 index 000000000..4c6336066 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftMethodEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.enums.cal; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 倒班方式枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesCalShiftMethodEnum implements ArrayValuable { + + QUARTER(1, "按季度"), + MONTH(2, "按月"), + WEEK(3, "按周"), + DAY(4, "按天"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesCalShiftMethodEnum::getMethod).toArray(Integer[]::new); + + /** + * 方式值 + */ + private final Integer method; + /** + * 方式名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftTypeEnum.java new file mode 100644 index 000000000..f801e1006 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftTypeEnum.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.mes.enums.cal; + +import cn.hutool.core.lang.Pair; +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.List; + +/** + * MES 轮班方式枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesCalShiftTypeEnum implements ArrayValuable { + + SINGLE(1, "单白班", List.of( + Pair.of("白班", new String[]{"08:00", "17:00"}) + )), + TWO(2, "两班倒", List.of( + Pair.of("白班", new String[]{"08:00", "20:00"}), + Pair.of("夜班", new String[]{"20:00", "08:00"}) + )), + THREE(3, "三班倒", List.of( + Pair.of("白班", new String[]{"08:00", "16:00"}), + Pair.of("中班", new String[]{"16:00", "00:00"}), + Pair.of("夜班", new String[]{"00:00", "08:00"}) + )); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesCalShiftTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + /** + * 班次配置列表 + * + * key: 班次名称(如 "白班", "夜班", "中班") + * value: [startTime, endTime](如 ["08:00", "17:00"]) + */ + private final List> shifts; + + /** + * 获取班次数量上限 + */ + public int getShiftCount() { + return shifts.size(); + } + + /** + * 获取所需的最少班组数量 + */ + public int getRequiredTeamCount() { + return shifts.size(); + } + + /** + * 根据类型值获取枚举 + */ + public static MesCalShiftTypeEnum valueOf(Integer type) { + for (MesCalShiftTypeEnum value : values()) { + if (value.getType().equals(type)) { + return value; + } + } + throw new IllegalArgumentException("不支持的轮班方式: " + type); + } + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanStatusEnum.java new file mode 100644 index 000000000..c37852082 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanStatusEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 点检保养方案状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvCheckPlanStatusEnum implements ArrayValuable { + + PREPARE(0, "草稿"), + ENABLED(1, "已启用"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvCheckPlanStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckRecordStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckRecordStatusEnum.java new file mode 100644 index 000000000..ce675a16a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckRecordStatusEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 设备点检记录状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvCheckRecordStatusEnum implements ArrayValuable { + + DRAFT(10, "草稿"), + FINISHED(20, "已完成"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvCheckRecordStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckResultEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckResultEnum.java new file mode 100644 index 000000000..6d1cd1e45 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckResultEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 设备点检结果枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvCheckResultEnum implements ArrayValuable { + + NORMAL(1, "正常"), + ABNORMAL(2, "异常"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvCheckResultEnum::getResult).toArray(Integer[]::new); + + /** + * 结果值 + */ + private final Integer result; + /** + * 结果名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMachineryStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMachineryStatusEnum.java new file mode 100644 index 000000000..4a1568a2b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMachineryStatusEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 设备状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvMachineryStatusEnum implements ArrayValuable { + + STOP(1, "停机"), + PRODUCING(2, "生产中"), + MAINTENANCE(3, "维护中"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvMachineryStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenRecordStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenRecordStatusEnum.java new file mode 100644 index 000000000..4ebf320f0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenRecordStatusEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 设备保养记录状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvMaintenRecordStatusEnum implements ArrayValuable { + + PREPARE(1, "草稿"), + SUBMITTED(2, "已提交"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvMaintenRecordStatusEnum::getStatus) + .toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenStatusEnum.java new file mode 100644 index 000000000..6b4ba2270 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenStatusEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 设备保养明细结果枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvMaintenStatusEnum implements ArrayValuable { + + NORMAL(1, "正常"), + ABNORMAL(2, "异常"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvMaintenStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvRepairResultEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvRepairResultEnum.java new file mode 100644 index 000000000..8e062593b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvRepairResultEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 维修结果枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvRepairResultEnum implements ArrayValuable { + + PASS(1, "通过"), + FAIL(2, "不通过"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvRepairResultEnum::getResult).toArray(Integer[]::new); + + /** + * 结果值 + */ + private final Integer result; + /** + * 结果名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvRepairStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvRepairStatusEnum.java new file mode 100644 index 000000000..c10698fb7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvRepairStatusEnum.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 维修工单状态枚举 + * + * 状态流转:草稿 → 维修中 → 待验收 → 已确认 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvRepairStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesDvRepairService#createRepair 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 维修中(提交后,维修人接单) + * + * 对应 MesDvRepairService#submitRepair 方法 + */ + CONFIRMED(MesOrderStatusConstants.CONFIRMED, "维修中"), + /** + * 待验收(维修完成,等待验收) + * + * 对应 MesDvRepairService#confirmRepair 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待验收"), + /** + * 已确认(验收通过或不通过,终态) + * + * 对应 MesDvRepairService#finishRepair 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已确认"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvRepairStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/MesMdItemTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/MesMdItemTypeEnum.java new file mode 100644 index 000000000..b39392e50 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/MesMdItemTypeEnum.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.enums.md; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * MES 物料产品分类 - 物料/产品标识枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesMdItemTypeEnum { + + /** + * 物料 + */ + ITEM("ITEM", "物料"), + /** + * 产品 + */ + PRODUCT("PRODUCT", "产品"); + + /** + * 标识值 + */ + private final String value; + /** + * 标识名 + */ + private final String name; + + /** + * 判断给定值是否为产品类型 + */ + public static boolean isProduct(String value) { + return PRODUCT.getValue().equals(value); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeCycleMethodEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeCycleMethodEnum.java new file mode 100644 index 000000000..315d9ced8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeCycleMethodEnum.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.enums.md.autocode; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 编码规则循环方式枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesMdAutoCodeCycleMethodEnum implements ArrayValuable { + + YEAR(1, "按年"), + MONTH(2, "按月"), + DAY(3, "按天"), + HOUR(4, "按小时"), + MINUTE(5, "按分钟"), + INPUT_CHAR(10, "按传入字符"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesMdAutoCodeCycleMethodEnum::getMethod).toArray(Integer[]::new); + + /** + * 方式 + */ + private final Integer method; + /** + * 名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePaddedMethodEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePaddedMethodEnum.java new file mode 100644 index 000000000..f13b91baa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePaddedMethodEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.md.autocode; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 编码规则补齐方式枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesMdAutoCodePaddedMethodEnum implements ArrayValuable { + + LEFT(1, "左补齐"), + RIGHT(2, "右补齐"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesMdAutoCodePaddedMethodEnum::getMethod).toArray(Integer[]::new); + + /** + * 方式 + */ + private final Integer method; + /** + * 名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePartTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePartTypeEnum.java new file mode 100644 index 000000000..864b818e3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePartTypeEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.enums.md.autocode; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 编码规则分段类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesMdAutoCodePartTypeEnum implements ArrayValuable { + + INPUT_CHAR(1, "输入字符"), + DATE(2, "当前日期"), + FIXED_CHAR(3, "固定字符"), + SERIAL_NUMBER(4, "流水号"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesMdAutoCodePartTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型 + */ + private final Integer type; + /** + * 名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java new file mode 100644 index 000000000..698ec85dd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.enums.md.autocode; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * MES 编码规则代码枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesMdAutoCodeRuleCodeEnum { + + MD_ITEM_CODE("MD_ITEM_CODE", "物料编码"), + MD_VENDOR_CODE("MD_VENDOR_CODE", "供应商编码"), + MD_CLIENT_CODE("MD_CLIENT_CODE", "客户编码"), + MD_WORKSTATION_CODE("MD_WORKSTATION_CODE", "工作站编码"), + TM_TOOL_TYPE_CODE("TM_TOOL_TYPE_CODE", "工具类型编码"), + WM_ARRIVAL_NOTICE_CODE("WM_ARRIVAL_NOTICE_CODE", "到货通知单编码"), + WM_ITEM_RECEIPT_CODE("WM_ITEM_RECEIPT_CODE", "采购入库单编码"), + WM_RETURN_VENDOR_CODE("WM_RETURN_VENDOR_CODE", "采购退货单编码"), + WM_RETURN_ISSUE_CODE("WM_RETURN_ISSUE_CODE", "生产退料单编码"), + WM_SN_CODE("WM_SN_CODE", "SN 码"), + WM_PACKAGE_CODE("WM_PACKAGE_CODE", "装箱单编码"), + WM_BATCH_CODE("WM_BATCH_CODE", "批次编码"), + PRO_TASK_CODE("PRO_TASK_CODE", "生产任务编码"), + QC_IQC_CODE("QC_IQC_CODE", "来料检验单编码"), + QC_IPQC_CODE("QC_IPQC_CODE", "过程检验单编码"), + QC_OQC_CODE("QC_OQC_CODE", "出货检验单编码"), + QC_RQC_CODE("QC_RQC_CODE", "退货检验单编码"), + WM_WAREHOUSE_CODE("WM_WAREHOUSE_CODE", "仓库编码"), + WM_LOCATION_CODE("WM_LOCATION_CODE", "库区编码"), + WM_AREA_CODE("WM_AREA_CODE", "库位编码"), + WM_PRODUCT_SALES_CODE("WM_PRODUCT_SALES_CODE", "销售出库单编码"), + WM_MISC_RECEIPT_CODE("WM_MISC_RECEIPT_CODE", "杂项入库单编码"), + WM_STOCK_TAKING_PLAN_CODE("WM_STOCK_TAKING_PLAN_CODE", "盘点方案编码"), + WM_STOCK_TAKING_CODE("WM_STOCK_TAKING_CODE", "盘点任务编码"), + TRANSFER_CODE("TRANSFER_CODE", "转移调拨单编码"), + WM_OUTSOURCE_ISSUE_CODE("WM_OUTSOURCE_ISSUE_CODE", "外协发料单编码"), + DV_MACHINERY_CODE("DV_MACHINERY_CODE", "设备编码"), + DV_MACHINERY_TYPE_CODE("DV_MACHINERY_TYPE_CODE", "设备类型编码"), + DV_SUBJECT_CODE("DV_SUBJECT_CODE", "点检保养项目编码"), + DV_REPAIR_CODE("DV_REPAIR_CODE", "维修单编码"), + WM_SALES_NOTICE_CODE("WM_SALES_NOTICE_CODE", "发货通知单编码"), + WM_RETURN_SALES_CODE("WM_RETURN_SALES_CODE", "销售退货单编码"), + WM_MISC_ISSUE_CODE("WM_MISC_ISSUE_CODE", "杂项出库单编码"), + PRO_ROUTE_CODE("PRO_ROUTE_CODE", "工艺路线编码"), + PRO_FEEDBACK_CODE("PRO_FEEDBACK_CODE", "生产报工单编码"), + PRO_WORK_ORDER_CODE("PRO_WORK_ORDER_CODE", "生产工单编码"), + QC_DEFECT_CODE("QC_DEFECT_CODE", "缺陷类型编码"), + QC_INDICATOR_RESULT_CODE("QC_INDICATOR_RESULT_CODE", "样品检验结果编码"), + WM_OUTSOURCE_RECEIPT_CODE("WM_OUTSOURCE_RECEIPT_CODE", "外协入库单编码"); + + /** + * 规则代码 + */ + private final String code; + /** + * 规则名称 + */ + private final String name; + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProAndonLevelEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProAndonLevelEnum.java new file mode 100644 index 000000000..d12c86192 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProAndonLevelEnum.java @@ -0,0 +1,38 @@ +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 MesProAndonLevelEnum implements ArrayValuable { + + LEVEL1(1, "一级"), + LEVEL2(2, "二级"), + LEVEL3(3, "三级"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProAndonLevelEnum::getLevel).toArray(Integer[]::new); + + /** + * 级别值 + */ + private final Integer level; + /** + * 级别名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProAndonStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProAndonStatusEnum.java new file mode 100644 index 000000000..3a7f75922 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProAndonStatusEnum.java @@ -0,0 +1,37 @@ +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 MesProAndonStatusEnum implements ArrayValuable { + + ACTIVE(0, "未处置"), + HANDLED(1, "已处置"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProAndonStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackStatusEnum.java new file mode 100644 index 000000000..cfa907668 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackStatusEnum.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.enums.pro; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 生产报工状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesProFeedbackStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesProFeedbackService#createFeedback 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 审批中 + * + * 对应 MesProFeedbackService#submitFeedback 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "审批中"), + /** + * 待检验(质检工序特有) + * + * 对应 MesProFeedbackService#submitFeedback 方法 + */ + UNCHECK(MesOrderStatusConstants.APPROVED, "待检验"), + /** + * 已完成 + * + * 对应 MesProFeedbackService#approveFeedback 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProFeedbackStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackTypeEnum.java new file mode 100644 index 000000000..14db1e361 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackTypeEnum.java @@ -0,0 +1,37 @@ +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 MesProFeedbackTypeEnum implements ArrayValuable { + + SELF(1, "自行报工"), + UNIFIED(2, "统一报工"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProFeedbackTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProLinkTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProLinkTypeEnum.java new file mode 100644 index 000000000..8ad8deb96 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProLinkTypeEnum.java @@ -0,0 +1,39 @@ +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 MesProLinkTypeEnum implements ArrayValuable { + + START_START(0, "开始-开始"), + FINISH_FINISH(1, "结束-结束"), + START_FINISH(2, "开始-结束"), + FINISH_START(3, "结束-开始"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProLinkTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java new file mode 100644 index 000000000..8f5ba7b40 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.enums.pro; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 生产任务状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesProTaskStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesProTaskService#createTask 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 已完成 + * + * 对应 MesProTaskService#finishTaskByOrderId 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesProTaskService#cancelTaskByOrderId 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProTaskStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + + /** + * 判断是否为终态(已完成 或 已取消) + * + * @param status 状态值 + * @return 是否为终态 + */ + public static boolean isEndStatus(Integer status) { + return ObjectUtils.equalsAny(status, FINISHED.status, CANCELED.status); + } + +} + diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderSourceTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderSourceTypeEnum.java new file mode 100644 index 000000000..47836b7df --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderSourceTypeEnum.java @@ -0,0 +1,37 @@ +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 MesProWorkOrderSourceTypeEnum implements ArrayValuable { + + ORDER(1, "客户订单"), + STORE(2, "库存备货"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProWorkOrderSourceTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderStatusEnum.java new file mode 100644 index 000000000..1bd2ffa59 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderStatusEnum.java @@ -0,0 +1,39 @@ +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 MesProWorkOrderStatusEnum implements ArrayValuable { + + PREPARE(0, "草稿"), + CONFIRMED(1, "已确认"), + FINISHED(2, "已完成"), + CANCELED(3, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProWorkOrderStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderTypeEnum.java new file mode 100644 index 000000000..3c7b15039 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderTypeEnum.java @@ -0,0 +1,38 @@ +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 MesProWorkOrderTypeEnum implements ArrayValuable { + + SELF(1, "自行生产"), + OUTSOURCE(2, "代工"), + PURCHASE(3, "采购"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProWorkOrderTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkRecordTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkRecordTypeEnum.java new file mode 100644 index 000000000..1629a0e04 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkRecordTypeEnum.java @@ -0,0 +1,37 @@ +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 MesProWorkRecordTypeEnum implements ArrayValuable { + + CLOCK_IN(1, "上工"), + CLOCK_OUT(2, "下工"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProWorkRecordTypeEnum::getType).toArray(Integer[]::new); + + /** + * 操作类型 + */ + private final Integer type; + /** + * 操作名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesTimeUnitTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesTimeUnitTypeEnum.java new file mode 100644 index 000000000..b6fa8b399 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesTimeUnitTypeEnum.java @@ -0,0 +1,38 @@ +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 MesTimeUnitTypeEnum implements ArrayValuable { + + MINUTE("MINUTE", "分钟"), + HOUR("HOUR", "小时"), + DAY("DAY", "天"); + + public static final String[] ARRAYS = Arrays.stream(values()).map(MesTimeUnitTypeEnum::getType).toArray(String[]::new); + + /** + * 类型值 + */ + private final String type; + /** + * 类型名 + */ + private final String name; + + @Override + public String[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcCheckResultEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcCheckResultEnum.java new file mode 100644 index 000000000..a8ae07cbc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcCheckResultEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.qc; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 检测结果枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesQcCheckResultEnum implements ArrayValuable { + + PASS(1, "检验通过"), + FAIL(2, "检验不通过"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcCheckResultEnum::getType).toArray(Integer[]::new); + + /** + * 结果值 + */ + private final Integer type; + /** + * 结果名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcDefectLevelEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcDefectLevelEnum.java new file mode 100644 index 000000000..0ceba0949 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcDefectLevelEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.enums.qc; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 缺陷等级枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesQcDefectLevelEnum implements ArrayValuable { + + CRITICAL(1, "致命"), + MAJOR(2, "严重"), + MINOR(3, "轻微"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcDefectLevelEnum::getType).toArray(Integer[]::new); + + /** + * 等级值 + */ + private final Integer type; + /** + * 等级名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcResultValueTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcResultValueTypeEnum.java new file mode 100644 index 000000000..659a42d72 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcResultValueTypeEnum.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.enums.qc; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 质检值类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesQcResultValueTypeEnum implements ArrayValuable { + + FLOAT(1, "浮点"), + INTEGER(2, "整数"), + TEXT(3, "文本"), + DICT(4, "字典"), + FILE(5, "文件"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcResultValueTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java new file mode 100644 index 000000000..01c8050d8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.mes.enums.qc; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 质检来源单据类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesQcSourceDocTypeEnum implements ArrayValuable { + + // === IQC 来源单据 === + ARRIVAL_NOTICE(MesBizTypeConstants.WM_ARRIVAL_NOTICE, "到货通知单"), + OUTSOURCE_RECPT(MesBizTypeConstants.WM_OUTSOURCE_RECPT, "外协入库单"), + + // === IPQC 来源单据 === + PRO_FEEDBACK(MesBizTypeConstants.PRO_FEEDBACK, "生产报工"), + + // === OQC 来源单据 === + PRODUCT_SALES(MesBizTypeConstants.WM_PRODUCT_SALES, "销售出库单"), + + // === RQC 来源单据 === + RETURN_ISSUE(MesBizTypeConstants.WM_RETURN_ISSUE, "生产退料单"), + RETURN_SALES(MesBizTypeConstants.WM_RETURN_SALES, "销售退货单"), + ; + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcSourceDocTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcStatusEnum.java new file mode 100644 index 000000000..c16bc6d57 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcStatusEnum.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.enums.qc; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 质检单状态枚举 + * + * 适用于:IQC(来料检验)、IPQC(过程检验)、OQC(出货检验)、RQC(退货检验) + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesQcStatusEnum implements ArrayValuable { + + DRAFT(MesOrderStatusConstants.PREPARE, "草稿"), + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"); + + public static final Integer[] ARRAYS = Arrays.stream(values()) + .map(MesQcStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.java new file mode 100644 index 000000000..c47c1ba18 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.enums.qc; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 检测种类枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesQcTypeEnum implements ArrayValuable { + + IQC(MesBizTypeConstants.QC_IQC, "来料检验"), + IPQC(MesBizTypeConstants.QC_IPQC, "过程检验"), + OQC(MesBizTypeConstants.QC_OQC, "出货检验"), + RQC(MesBizTypeConstants.QC_RQC, "退货检验"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/tm/MesTmMaintenTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/tm/MesTmMaintenTypeEnum.java new file mode 100644 index 000000000..16cdffcb2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/tm/MesTmMaintenTypeEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.tm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 保养维护类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesTmMaintenTypeEnum implements ArrayValuable { + + REGULAR(1, "定期维护"), + USAGE(2, "按使用次数维护"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesTmMaintenTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/tm/MesTmToolStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/tm/MesTmToolStatusEnum.java new file mode 100644 index 000000000..5152bd398 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/tm/MesTmToolStatusEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.enums.tm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 工具状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesTmToolStatusEnum implements ArrayValuable { + + STORE(1, "在库"), + ISSUE(2, "领用中"), + REPAIR(3, "维修中"), + SCRAP(4, "报废"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesTmToolStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/BarcodeBizTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/BarcodeBizTypeEnum.java new file mode 100644 index 000000000..4b25d41c9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/BarcodeBizTypeEnum.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 条码业务类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum BarcodeBizTypeEnum implements ArrayValuable { + + WAREHOUSE(MesBizTypeConstants.WM_WAREHOUSE, "仓库"), + LOCATION(MesBizTypeConstants.WM_LOCATION, "库区"), + AREA(MesBizTypeConstants.WM_AREA, "库位"), + PACKAGE(MesBizTypeConstants.WM_PACKAGE, "装箱单"), + STOCK(MesBizTypeConstants.WM_STOCK, "库存"), + BATCH(MesBizTypeConstants.WM_BATCH, "批次"), + PROCARD(MesBizTypeConstants.PRO_CARD, "流转卡"), + WORKORDER(MesBizTypeConstants.PRO_WORKORDER, "工单"), + TRANSORDER(MesBizTypeConstants.PRO_TRANS_ORDER, "流转单"), + MACHINERY(MesBizTypeConstants.DV_MACHINERY, "设备"), + TOOL(MesBizTypeConstants.TM_TOOL, "工具"), + ITEM(MesBizTypeConstants.MD_ITEM, "物料"), + VENDOR(MesBizTypeConstants.MD_VENDOR, "供应商"), + CLIENT(MesBizTypeConstants.MD_CLIENT, "客户"), + WORKSTATION(MesBizTypeConstants.MD_WORKSTATION, "工作站"), + WORKSHOP(MesBizTypeConstants.MD_WORKSHOP, "车间"), + USER(MesBizTypeConstants.MD_USER, "人员"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(BarcodeBizTypeEnum::getValue).toArray(Integer[]::new); + + /** + * 业务类型值 + */ + private final Integer value; + /** + * 业务类型名称 + */ + private final String label; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/BarcodeFormatEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/BarcodeFormatEnum.java new file mode 100644 index 000000000..ef1c900d3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/BarcodeFormatEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 条码格式枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum BarcodeFormatEnum implements ArrayValuable { + + QR_CODE(1, "二维码"), + EAN13(2, "EAN13 商品条码"), + CODE39(3, "CODE39 工业条码"), + UPC_A(4, "UPC-A 美国商品码"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(BarcodeFormatEnum::getValue).toArray(Integer[]::new); + + /** + * 格式值 + */ + private final Integer value; + /** + * 格式名称 + */ + private final String label; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmArrivalNoticeStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmArrivalNoticeStatusEnum.java new file mode 100644 index 000000000..25acc1543 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmArrivalNoticeStatusEnum.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 到货通知单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmArrivalNoticeStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmArrivalNoticeService#createArrivalNotice 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待质检(需要检验时),对接 qc 模块的 MesQcIqcDO 后续流程 + * + * 对应 MesWmArrivalNoticeService#submitArrivalNotice 方法 + */ + PENDING_QC(MesOrderStatusConstants.APPROVING, "待质检"), + /** + * 待入库(不需要检验时,或检验完成时),对接 wm 模块的 MesWmItemReceiptDO 后续流程 + * + * 对应方法: + * 1. 不需要检验时:MesWmArrivalNoticeService#submitArrivalNotice 方法 + * 2. 或检验完成时:MesWmArrivalNoticeService#updateArrivalNoticeWhenIqcFinish 方法 + */ + PENDING_RECEIPT(MesOrderStatusConstants.APPROVED, "待入库"), + /** + * 已完成 + * + * 对应 MesWmArrivalNoticeService#finishArrivalNotice 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmArrivalNoticeStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmItemConsumeStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmItemConsumeStatusEnum.java new file mode 100644 index 000000000..c510555b6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmItemConsumeStatusEnum.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 物料消耗记录状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmItemConsumeStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmItemConsumeService#generateItemConsume 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 已完成 + * + * 对应 MesWmItemConsumeService#finishItemConsume 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmItemConsumeStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmItemReceiptStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmItemReceiptStatusEnum.java new file mode 100644 index 000000000..4b1a80abf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmItemReceiptStatusEnum.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 采购入库单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmItemReceiptStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmItemReceiptService#createItemReceipt 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待上架 + * + * 对应 MesWmItemReceiptService#submitItemReceipt 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待上架"), + /** + * 待入库 + * + * 对应 MesWmItemReceiptService#stockItemReceipt 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行入库"), + /** + * 已完成 + * + * 对应 MesWmItemReceiptService#finishItemReceipt 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmItemReceiptService#cancelItemReceipt 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmItemReceiptStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscIssueStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscIssueStatusEnum.java new file mode 100644 index 000000000..17168f48a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscIssueStatusEnum.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 杂项出库单状态枚举 + * + * 对应字典 mes_wm_misc_issue_status + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmMiscIssueStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmMiscIssueService#createMiscIssue 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待执行出库 + * + * 对应 MesWmMiscIssueService#submitMiscIssue 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行出库"), + /** + * 已完成 + * + * 对应 MesWmMiscIssueService#finishMiscIssue 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmMiscIssueService#cancelMiscIssue 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmMiscIssueStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscIssueTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscIssueTypeEnum.java new file mode 100644 index 000000000..5162329d0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscIssueTypeEnum.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum MesWmMiscIssueTypeEnum implements ArrayValuable { + + ADJUST(1, "库存调整"), + SCRAP(2, "报废出库"); + + private final Integer type; + private final String name; + + @Override + public Integer[] array() { + return Arrays.stream(values()).map(MesWmMiscIssueTypeEnum::getType).toArray(Integer[]::new); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptStatusEnum.java new file mode 100644 index 000000000..8fc3092c8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptStatusEnum.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 杂项入库单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmMiscReceiptStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmMiscReceiptService#createMiscReceipt 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 已审批 + * + * 对应 MesWmMiscReceiptService#submitMiscReceipt 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "已审批"), + /** + * 已完成 + * + * 对应 MesWmMiscReceiptService#finishMiscReceipt 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmMiscReceiptService#cancelMiscReceipt 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmMiscReceiptStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptTypeEnum.java new file mode 100644 index 000000000..072637efb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptTypeEnum.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 杂项入库类型枚举 + */ +@Getter +@AllArgsConstructor +public enum MesWmMiscReceiptTypeEnum implements ArrayValuable { + + ADJUST(1, "库存调整"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmMiscReceiptTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceIssueStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceIssueStatusEnum.java new file mode 100644 index 000000000..8569a982d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceIssueStatusEnum.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 外协发料单状态枚举 + * + * 对应字典 mes_wm_outsource_issue_status + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmOutsourceIssueStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmOutsourceIssueService#createOutsourceIssue 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待拣货 + * + * 对应 MesWmOutsourceIssueService#submitOutsourceIssue 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待拣货"), + /** + * 待执行出库 + * + * 对应 MesWmOutsourceIssueService#stockOutsourceIssue 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行出库"), + /** + * 已完成 + * + * 对应 MesWmOutsourceIssueService#finishOutsourceIssue 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmOutsourceIssueService#cancelOutsourceIssue 方法 + */ + CANCELLED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmOutsourceIssueStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceReceiptStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceReceiptStatusEnum.java new file mode 100644 index 000000000..5024a5f2f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmOutsourceReceiptStatusEnum.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 外协入库单状态枚举 + * + * 对应字典 mes_wm_outsource_receipt_status + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmOutsourceReceiptStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmOutsourceReceiptService#createOutsourceReceipt 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待检验(已确认,等待质检) + * + * 对应 MesWmOutsourceReceiptService#submitOutsourceReceipt 方法 + */ + CONFIRMED(MesOrderStatusConstants.CONFIRMED, "待检验"), + /** + * 待上架(检验完成,等待仓库上架) + * + * 对应 MesWmOutsourceReceiptService#submitOutsourceReceipt 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待上架"), + /** + * 待执行入库(上架完成,等待执行入库操作) + * + * 对应 MesWmOutsourceReceiptService#stockOutsourceReceipt 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行入库"), + /** + * 已完成(入库执行完成,库存已更新) + * + * 对应 MesWmOutsourceReceiptService#finishOutsourceReceipt 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmOutsourceReceiptService#cancelOutsourceReceipt 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmOutsourceReceiptStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmPackageStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmPackageStatusEnum.java new file mode 100644 index 000000000..54820b8cf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmPackageStatusEnum.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 装箱单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmPackageStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmPackageService#createPackage 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 已完成 + * + * 对应 MesWmPackageService#finishPackage 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmPackageStatusEnum::getStatus) + .toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductIssueStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductIssueStatusEnum.java new file mode 100644 index 000000000..e395e6c33 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductIssueStatusEnum.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 领料出库单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmProductIssueStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmProductIssueService#createProductIssue 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待拣货 + * + * 对应 MesWmProductIssueService#submitProductIssue 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待拣货"), + /** + * 待执行领出 + * + * 对应 MesWmProductIssueService#stockProductIssue 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行领出"), + /** + * 已完成 + * + * 对应 MesWmProductIssueService#finishProductIssue 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmProductIssueService#cancelProductIssue 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmProductIssueStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductProduceStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductProduceStatusEnum.java new file mode 100644 index 000000000..e89c29c23 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductProduceStatusEnum.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 生产入库单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmProductProduceStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmProductProduceService#generateProductProduce 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 已完成 + * + * 对应 MesWmProductProduceService#finishProductProduce 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmProductProduceStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductReceiptStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductReceiptStatusEnum.java new file mode 100644 index 000000000..707dfad0d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductReceiptStatusEnum.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 产品入库单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmProductReceiptStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmProductReceiptService#createProductReceipt 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待上架 + * + * 对应 MesWmProductReceiptService#submitProductReceipt 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待上架"), + /** + * 待执行入库 + * + * 对应 MesWmProductReceiptService#stockProductReceipt 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行入库"), + /** + * 已完成 + * + * 对应 MesWmProductReceiptService#finishProductReceipt 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmProductReceiptService#cancelProductReceipt 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmProductReceiptStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductSalesStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductSalesStatusEnum.java new file mode 100644 index 000000000..34325040b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductSalesStatusEnum.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 销售出库单状态枚举 + * + * 对应字典 mes_wm_product_sales_status + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmProductSalesStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmProductSalesService#createProductSales 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待检测(需要 OQC 检验时),对接 qc 模块的 MesQcOqcDO 后续流程 + * + * 对应 MesWmProductSalesService#submitProductSales 方法 + */ + CONFIRMED(MesOrderStatusConstants.CONFIRMED, "待检测"), + /** + * 待拣货 + * + * 对应方法: + * 1. 不需要 OQC 检验时:MesWmProductSalesService#submitProductSales 方法 + * 2. 或 OQC 检验完成时:MesWmProductSalesService#confirmProductSales 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待拣货"), + /** + * 待填写运单 + * + * 对应 MesWmProductSalesService#shippingProductSales 方法 + */ + SHIPPING(10, "待填写运单"), // 10 是一个特殊的状态值,不在 MesOrderStatusConstants 中,单独定义 + /** + * 待执行出库 + * + * 对应 MesWmProductSalesService#stockProductSales 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行出库"), + /** + * 已完成 + * + * 对应 MesWmProductSalesService#finishProductSales 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmProductSalesService#cancelProductSales 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmProductSalesStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmQualityStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmQualityStatusEnum.java new file mode 100644 index 000000000..00bd23332 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmQualityStatusEnum.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 质量状态枚举 + * + * 对应字典 mes_wm_quality_status + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmQualityStatusEnum implements ArrayValuable { + + /** + * 待检验 + */ + PENDING(0, "待检验"), + /** + * 合格 + */ + PASS(1, "合格"), + /** + * 不合格 + */ + FAIL(2, "不合格"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmQualityStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnIssueStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnIssueStatusEnum.java new file mode 100644 index 000000000..2b90d96f8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnIssueStatusEnum.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 生产退料单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmReturnIssueStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmReturnIssueService#createReturnIssue 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待检验(已确认,等待质检) + * + * 对应 MesWmReturnIssueService#submitReturnIssue 方法 + */ + CONFIRMED(MesOrderStatusConstants.CONFIRMED, "待检验"), // "UNCHECK" + /** + * 待上架(检验完成,等待仓库上架) + * + * 对应 MesWmReturnIssueService#submitReturnIssue 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待上架"), // "UNSTOCK" + /** + * 待执行退料(上架完成,等待执行退料操作) + * + * 对应 MesWmReturnIssueService#stockReturnIssue 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行退料"), // "UNEXECUTE" + /** + * 已完成(退料执行完成,库存已更新) + * + * 对应 MesWmReturnIssueService#finishReturnIssue 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmReturnIssueService#cancelReturnIssue 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmReturnIssueStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} + +// DONE @AI:状态流转逻辑已在 MesWmReturnIssueServiceImpl 中实现,参考 confirmReturnIssue、submitReturnIssue、stockReturnIssue、finishReturnIssue 方法 diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnIssueTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnIssueTypeEnum.java new file mode 100644 index 000000000..e57904ff4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnIssueTypeEnum.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 生产退料类型枚举 + * + * 对应字典 mes_wm_return_issue_type + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmReturnIssueTypeEnum implements ArrayValuable { + + /** + * 余料退料(余料退回,直接合格) + */ + REMAINDER(1, "余料退料"), + /** + * 不良退料(不良品退回) + */ + DEFECTIVE(2, "不良退料"), + /** + * 其他退料(其他原因退料) + */ + OTHER(3, "其他退料"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmReturnIssueTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnSalesStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnSalesStatusEnum.java new file mode 100644 index 000000000..2b75e5996 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnSalesStatusEnum.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 销售退货单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmReturnSalesStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmReturnSalesService#createReturnSales 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待检验(已确认,等待质检) + * + * 对应 MesWmReturnSalesService#submitReturnSales 方法 + */ + CONFIRMED(MesOrderStatusConstants.CONFIRMED, "待检验"), // "UNCHECK" + /** + * 待执行(检验完成或免检,等待执行退货) + * + * 对应 MesWmReturnSalesService#submitReturnSales 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待执行"), // "UNEXECUTE" + /** + * 待上架(退货执行完成,等待仓库上架) + * + * 对应 MesWmReturnSalesService#finishReturnSales 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待上架"), // "UNSTOCK" + /** + * 已完成(上架完成,库存已更新) + * + * 对应 MesWmReturnSalesService#stockReturnSales 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmReturnSalesService#cancelReturnSales 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmReturnSalesStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnVendorStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnVendorStatusEnum.java new file mode 100644 index 000000000..1c8bc68de --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmReturnVendorStatusEnum.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 供应商退货单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmReturnVendorStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmReturnVendorService#createReturnVendor 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待拣货 + * + * 对应 MesWmReturnVendorService#submitReturnVendor 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待拣货"), + /** + * 待执行退货 + * + * 对应 MesWmReturnVendorService#stockReturnVendor 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行退货"), + /** + * 已完成 + * + * 对应 MesWmReturnVendorService#finishReturnVendor 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmReturnVendorService#cancelReturnVendor 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmReturnVendorStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmSalesNoticeStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmSalesNoticeStatusEnum.java new file mode 100644 index 000000000..01ab066a7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmSalesNoticeStatusEnum.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 发货通知单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmSalesNoticeStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmSalesNoticeService#createSalesNotice 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待出库,对接 wm 模块的 MesWmProductSalesDO 后续流程 + * + * 对应 MesWmSalesNoticeService#submitSalesNotice 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待出库"); + // TODO @芋艿:【对齐】暂时无后续流程,看看后续要怎么支持下。 + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmSalesNoticeStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingPlanParamTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingPlanParamTypeEnum.java new file mode 100644 index 000000000..d45078a84 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingPlanParamTypeEnum.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 盘点方案参数类型枚举 + */ +@Getter +@AllArgsConstructor +public enum MesWmStockTakingPlanParamTypeEnum implements ArrayValuable { + + WAREHOUSE(MesBizTypeConstants.WM_WAREHOUSE, "仓库"), + LOCATION(MesBizTypeConstants.WM_LOCATION, "库区"), + AREA(MesBizTypeConstants.WM_AREA, "库位"), + ITEM(MesBizTypeConstants.MD_ITEM, "物料"), + BATCH(MesBizTypeConstants.WM_BATCH, "批次"), + QUALITY_STATUS(MesBizTypeConstants.QUALITY_STATUS, "质量状态"); + + public static final Integer[] ARRAYS = Arrays.stream(values()) + .map(MesWmStockTakingPlanParamTypeEnum::getType).toArray(Integer[]::new); + + /** + * 参数类型 + */ + private final Integer type; + /** + * 类型名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTaskLineStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTaskLineStatusEnum.java new file mode 100644 index 000000000..b5448a9bb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTaskLineStatusEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 盘点任务行状态枚举 + */ +@Getter +@AllArgsConstructor +public enum MesWmStockTakingTaskLineStatusEnum implements ArrayValuable { + + NORMAL(1, "正常"), + GAIN(2, "盘盈"), + LOSS(3, "盘亏"); + + public static final Integer[] ARRAYS = Arrays.stream(values()) + .map(MesWmStockTakingTaskLineStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态 + */ + private final Integer status; + /** + * 状态名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTaskStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTaskStatusEnum.java new file mode 100644 index 000000000..7756783f8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTaskStatusEnum.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 盘点任务状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmStockTakingTaskStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmStockTakingTaskService#createStockTakingTask 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 审批中 + * + * 对应 MesWmStockTakingTaskService#submitStockTakingTask 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "审批中"), + /** + * 已完成 + * + * 对应 MesWmStockTakingTaskService#finishStockTakingTask 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmStockTakingTaskService#cancelStockTakingTask 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()) + .map(MesWmStockTakingTaskStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态 + */ + private final Integer status; + /** + * 状态名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTypeEnum.java new file mode 100644 index 000000000..5538fd993 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmStockTakingTypeEnum.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 盘点类型枚举 + */ +@Getter +@AllArgsConstructor +public enum MesWmStockTakingTypeEnum implements ArrayValuable { + + STATIC(1, "静态盘点"), + DYNAMIC(2, "动态盘点"); + + public static final Integer[] ARRAYS = Arrays.stream(values()) + .map(MesWmStockTakingTypeEnum::getType).toArray(Integer[]::new); + + /** + * 盘点类型 + */ + private final Integer type; + /** + * 类型名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransactionTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransactionTypeEnum.java new file mode 100644 index 000000000..ec1471526 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransactionTypeEnum.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 库存事务类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmTransactionTypeEnum implements ArrayValuable { + + /** + * 入库 + */ + IN(1, "入库", true), + /** + * 出库 + */ + OUT(2, "出库", false), + /** + * 调拨移出 + */ + MOVE_OUT(3, "调拨移出", false), + /** + * 调拨移入 + */ + MOVE_IN(4, "调拨移入", true), + /** + * 盘盈 + */ + ADJUST_IN(5, "盘盈", true), + /** + * 盘亏 + */ + ADJUST_OUT(6, "盘亏", false); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmTransactionTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + /** + * 是否为入库方向 + */ + private final boolean inbound; + + public static MesWmTransactionTypeEnum valueOf(Integer type) { + return CollUtil.findOne(CollUtil.newArrayList(values()), + e -> ObjUtil.equal(e.getType(), type)); + } + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransferStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransferStatusEnum.java new file mode 100644 index 000000000..d57bc1d3d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransferStatusEnum.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 转移单状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmTransferStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应 MesWmTransferService#createTransfer 方法 + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 待确认(仅配送模式) + * + * 对应 MesWmTransferService#submitTransfer 方法 + */ + UNCONFIRMED(MesOrderStatusConstants.CONFIRMED, "待确认"), + /** + * 待上架 + * + * 对应 MesWmTransferService#submitTransfer 方法、MesWmTransferService#confirmTransfer 方法 + */ + APPROVING(MesOrderStatusConstants.APPROVING, "待上架"), + /** + * 待执行 + * + * 对应 MesWmTransferService#stockTransfer 方法 + */ + APPROVED(MesOrderStatusConstants.APPROVED, "待执行"), + /** + * 已完成 + * + * 对应 MesWmTransferService#finishTransfer 方法 + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应 MesWmTransferService#cancelTransfer 方法 + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmTransferStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransferTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransferTypeEnum.java new file mode 100644 index 000000000..7b9356062 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmTransferTypeEnum.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.enums.wm; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 转移单类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesWmTransferTypeEnum implements ArrayValuable { + + /** + * 内部调拨 + */ + INNER(1, "内部调拨"), + /** + * 外部调拨 + */ + OUTER(2, "外部调拨"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmTransferTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + public static MesWmTransferTypeEnum valueOf(Integer type) { + return Arrays.stream(values()).filter(e -> e.getType().equals(type)).findFirst().orElse(null); + } + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/Dockerfile b/yudao-module-mes/yudao-module-mes-server/Dockerfile new file mode 100644 index 000000000..bf00536e1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/Dockerfile @@ -0,0 +1,19 @@ +## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性 +## 感谢复旦核博士的建议!灰子哥,牛皮! +FROM eclipse-temurin:21-jre + +## 创建目录,并使用它作为工作目录 +RUN mkdir -p /yudao-module-mes-server +WORKDIR /yudao-module-mes-server +## 将后端项目的 Jar 文件,复制到镜像中 +COPY ./target/yudao-module-mes-server.jar app.jar + +## 设置 TZ 时区 +## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖 +ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m" + +## 暴露后端项目的 48091 端口 +EXPOSE 48091 + +## 启动后端项目 +CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar diff --git a/yudao-module-mes/yudao-module-mes-server/pom.xml b/yudao-module-mes/yudao-module-mes-server/pom.xml new file mode 100644 index 000000000..c8956ccb0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/pom.xml @@ -0,0 +1,119 @@ + + + + cn.iocoder.cloud + yudao-module-mes + ${revision} + + 4.0.0 + yudao-module-mes-server + + ${project.artifactId} + + mes 包下,制造执行系统(Manufacturing Execution System)。 + 例如说:基础数据、排班日历、设备管理、工具管理、生产管理、质量管理、仓库管理等等 + + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-env + + + + + cn.iocoder.cloud + yudao-module-system-api + ${revision} + + + cn.iocoder.cloud + yudao-module-mes-api + ${revision} + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-biz-tenant + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-security + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-mybatis + + + + cn.iocoder.cloud + yudao-spring-boot-starter-redis + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-rpc + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-excel + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-monitor + + + + + cn.iocoder.cloud + yudao-spring-boot-starter-test + + + + + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + + + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/MesServerApplication.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/MesServerApplication.java new file mode 100644 index 000000000..fc5c5cafe --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/MesServerApplication.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * 项目的启动类 + *

+ * 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + * 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + * 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + * + * @author 芋道源码 + */ +@SpringBootApplication +public class MesServerApplication { + + public static void main(String[] args) { + // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + + SpringApplication.run(MesServerApplication.class, args); + + // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + // 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章 + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/MesCalCalendarController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/MesCalCalendarController.java new file mode 100644 index 000000000..a7345534e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/MesCalCalendarController.java @@ -0,0 +1,212 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.calendar; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalHolidayTypeEnum; +import cn.iocoder.yudao.module.mes.service.cal.holiday.MesCalHolidayService; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamMemberService; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; + +@Tag(name = "管理后台 - MES 排班日历") +@RestController +@RequestMapping("/mes/cal/calendar") +@Validated +public class MesCalCalendarController { + + @Resource + private MesCalTeamShiftService teamShiftService; + @Resource + private MesCalTeamService teamService; + @Resource + private MesCalPlanShiftService planShiftService; + @Resource + private MesCalPlanService planService; + @Resource + private MesCalTeamMemberService teamMemberService; + @Resource + private MesCalHolidayService holidayService; + + @GetMapping("/list") + @Operation(summary = "查询排班日历") + @PreAuthorize("@ss.hasPermission('mes:cal-team-shift:query')") + public CommonResult> getCalendarList(@Valid MesCalCalendarListReqVO reqVO) { + // 1.1 根据查询类型获取班组排班记录 + List teamShifts = getTeamShifts(reqVO); + if (CollUtil.isEmpty(teamShifts)) { + return success(Collections.emptyList()); + } + // 1.2 按日期范围查询假期,构建节假日日期集合 + Set holidaySet = buildHolidaySet(reqVO.getStartDay(), reqVO.getEndDay()); + // 1.3 批量查询关联数据:班组、班次、排班计划 + Map teamMap = teamService.getTeamMap( + convertSet(teamShifts, MesCalTeamShiftDO::getTeamId)); + Map shiftMap = planShiftService.getPlanShiftMap( + convertSet(teamShifts, MesCalTeamShiftDO::getShiftId)); + Map planMap = planService.getPlanMap( + convertSet(teamShifts, MesCalTeamShiftDO::getPlanId)); + + // 2. 按 day 分组聚合 + Map> dayGroupMap = convertMultiMap(teamShifts, + teamShift -> LocalDateTimeUtil.format(teamShift.getDay(), DatePattern.NORM_DATE_PATTERN)); + + // 3. 遍历分组,过滤假期,构建日历响应 + List result = new ArrayList<>(); + for (Map.Entry> entry : dayGroupMap.entrySet()) { + String dayStr = entry.getKey(); + // 3.1 过滤节假日 + if (holidaySet.contains(dayStr)) { + continue; + } + List dayShifts = entry.getValue(); + dayShifts.sort(Comparator.comparing(ts -> ts.getSort() != null ? ts.getSort() : 0)); + // 3.2 获取轮班方式(取第一条记录关联的排班计划) + Integer shiftType = null; + MesCalTeamShiftDO first = dayShifts.get(0); + if (first.getPlanId() != null) { + MesCalPlanDO plan = planMap.get(first.getPlanId()); + if (plan != null) { + shiftType = plan.getShiftType(); + } + } + // 3.3 构建班组排班项列表 + List items = convertList(dayShifts, + teamShift -> buildTeamShiftItem(teamShift, teamMap, shiftMap)); + + // 3.4 构建日历项,添加到结果列表 + MesCalCalendarRespVO calendarVO = MesCalCalendarRespVO.builder() + .day(LocalDateTimeUtil.parseDate(dayStr, DatePattern.NORM_DATE_FORMATTER).atStartOfDay()) + .shiftType(shiftType) + .teamShifts(items) + .build(); + result.add(calendarVO); + } + return success(result); + } + + /** + * 根据查询类型获取班组排班记录 + */ + @SuppressWarnings("EnhancedSwitchMigration") + private List getTeamShifts(MesCalCalendarListReqVO reqVO) { + LocalDateTime startDay = reqVO.getStartDay(); + LocalDateTime endDay = reqVO.getEndDay(); + switch (reqVO.getQueryType()) { + case MesCalCalendarListReqVO.QUERY_TYPE_TYPE: + return getTeamShiftsByCalendarType(reqVO.getCalendarType(), startDay, endDay); + case MesCalCalendarListReqVO.QUERY_TYPE_TEAM: + return getTeamShiftsByTeamId(reqVO.getTeamId(), startDay, endDay); + case MesCalCalendarListReqVO.QUERY_TYPE_USER: + return getTeamShiftsByUserId(reqVO.getUserId(), startDay, endDay); + default: + return Collections.emptyList(); + } + } + + /** + * 构建单条 TeamShiftItem + */ + private MesCalCalendarRespVO.TeamShiftItem buildTeamShiftItem(MesCalTeamShiftDO ts, + Map teamMap, + Map shiftMap) { + MesCalTeamDO team = teamMap.get(ts.getTeamId()); + MesCalPlanShiftDO shift = shiftMap.get(ts.getShiftId()); + return MesCalCalendarRespVO.TeamShiftItem.builder() + .teamId(ts.getTeamId()).teamName(team != null ? team.getName() : null) + .shiftId(ts.getShiftId()).shiftName(shift != null ? shift.getName() : null) + .sort(ts.getSort()).build(); + } + + /** + * 按班组类型查询排班记录 + */ + private List getTeamShiftsByCalendarType(Integer calendarType, + LocalDateTime startDay, LocalDateTime endDay) { + if (calendarType == null) { + return Collections.emptyList(); + } + // 1. 查询指定类型的所有班组 + List teams = teamService.getTeamList().stream() + .filter(t -> calendarType.equals(t.getCalendarType())) + .collect(Collectors.toList()); + if (CollUtil.isEmpty(teams)) { + return Collections.emptyList(); + } + // 2. 一次 IN 查询这些班组在日期范围内的排班记录 + MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO() + .setTeamIds(convertSet(teams, MesCalTeamDO::getId)) + .setStartDay(startDay).setEndDay(endDay); + return teamShiftService.getTeamShiftList(reqVO); + } + + /** + * 按班组编号查询排班记录 + */ + private List getTeamShiftsByTeamId(Long teamId, LocalDateTime startDay, LocalDateTime endDay) { + if (teamId == null) { + return Collections.emptyList(); + } + MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO() + .setTeamId(teamId).setStartDay(startDay).setEndDay(endDay); + return teamShiftService.getTeamShiftList(reqVO); + } + + /** + * 按用户编号查询排班记录(先查用户所属班组,再查班组排班) + */ + private List getTeamShiftsByUserId(Long userId, + LocalDateTime startDay, LocalDateTime endDay) { + if (userId == null) { + return Collections.emptyList(); + } + // 1. 查询用户所属的班组(一个用户只属于一个班组) + MesCalTeamMemberDO member = teamMemberService.getTeamMemberByUserId(userId); + if (member == null) { + return Collections.emptyList(); + } + // 2. 查询该班组在日期范围内的排班记录 + MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO() + .setTeamId(member.getTeamId()).setStartDay(startDay).setEndDay(endDay); + return teamShiftService.getTeamShiftList(reqVO); + } + + /** + * 按日期范围查询假期,构建节假日日期集合(yyyy-MM-dd 格式) + */ + private Set buildHolidaySet(LocalDateTime startDay, LocalDateTime endDay) { + List holidays = holidayService.getHolidayList(startDay, endDay); + return convertSet(holidays, + holiday -> LocalDateTimeUtil.format(holiday.getDay(), DatePattern.NORM_DATE_PATTERN), + holiday -> MesCalHolidayTypeEnum.HOLIDAY.getType().equals(holiday.getType())); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarListReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarListReqVO.java new file mode 100644 index 000000000..ac4774dad --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarListReqVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 排班日历查询 Request VO") +@Data +public class MesCalCalendarListReqVO { + + public static final String QUERY_TYPE_TYPE = "TYPE"; + public static final String QUERY_TYPE_TEAM = "TEAM"; + public static final String QUERY_TYPE_USER = "USER"; + + @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "开始日期不能为空") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime startDay; + + @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "结束日期不能为空") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime endDay; + + @Schema(description = "查询类型:TYPE-按分类,TEAM-按班组,USER-按个人", requiredMode = Schema.RequiredMode.REQUIRED, example = "TYPE") + @NotEmpty(message = "查询类型不能为空") + private String queryType; + + @Schema(description = "班组类型(queryType=TYPE 时使用)", example = "1") + private Integer calendarType; + + @Schema(description = "班组编号(queryType=TEAM 时使用)", example = "201") + private Long teamId; + + @Schema(description = "用户编号(queryType=USER 时使用)", example = "1") + private Long userId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarRespVO.java new file mode 100644 index 000000000..254857ea7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarRespVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - MES 排班日历 Response VO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesCalCalendarRespVO { + + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2025-01-15 00:00:00") + private LocalDateTime day; + + @Schema(description = "轮班方式", example = "2") + private Integer shiftType; // 对应 MesCalShiftTypeEnum 枚举值 + + @Schema(description = "班组排班列表") + private List teamShifts; + + @Schema(description = "班组排班项") + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class TeamShiftItem { + + @Schema(description = "班组编号", example = "201") + private Long teamId; + + @Schema(description = "班组名称", example = "注塑A组") + private String teamName; + + @Schema(description = "班次编号", example = "1") + private Long shiftId; + + @Schema(description = "班次名称", example = "白班") + private String shiftName; + + @Schema(description = "排序", example = "1") + private Integer sort; + + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/MesCalHolidayController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/MesCalHolidayController.java new file mode 100644 index 000000000..a8cfd0915 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/MesCalHolidayController.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.holiday; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo.MesCalHolidayRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo.MesCalHolidaySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO; +import cn.iocoder.yudao.module.mes.service.cal.holiday.MesCalHolidayService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 假期设置") +@RestController +@RequestMapping("/mes/cal/holiday") +@Validated +public class MesCalHolidayController { + + @Resource + private MesCalHolidayService holidayService; + + @PostMapping("/save") + @Operation(summary = "保存假期设置", description = "如果该日期已存在记录,则更新") + @PreAuthorize("@ss.hasPermission('mes:cal-holiday:create')") + public CommonResult saveHoliday(@Valid @RequestBody MesCalHolidaySaveReqVO saveReqVO) { + return success(holidayService.saveHoliday(saveReqVO)); + } + + @GetMapping("/get-by-day") + @Operation(summary = "根据日期获得假期设置") + @Parameter(name = "day", description = "日期", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-holiday:query')") + public CommonResult getHolidayByDay( + @RequestParam("day") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime day) { + MesCalHolidayDO holiday = holidayService.getHolidayByDay(day); + return success(BeanUtils.toBean(holiday, MesCalHolidayRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得假期设置列表", description = "支持可选日期范围过滤,不传则返回全量数据") + @PreAuthorize("@ss.hasPermission('mes:cal-holiday:query')") + public CommonResult> getHolidayList( + @RequestParam(value = "startDay", required = false) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime startDay, + @RequestParam(value = "endDay", required = false) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) LocalDateTime endDay) { + List list = holidayService.getHolidayList(startDay, endDay); + return success(BeanUtils.toBean(list, MesCalHolidayRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidayRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidayRespVO.java new file mode 100644 index 000000000..cfde7a045 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidayRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 假期设置 Response VO") +@Data +public class MesCalHolidayRespVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "日期") + private LocalDateTime day; + + @Schema(description = "日期类型") + private Integer type; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidaySaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidaySaveReqVO.java new file mode 100644 index 000000000..0a8517271 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/holiday/vo/MesCalHolidaySaveReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 假期设置新增/修改 Request VO") +@Data +public class MesCalHolidaySaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "日期不能为空") + private LocalDateTime day; + + @Schema(description = "日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "日期类型不能为空") + private Integer type; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/package-info.java new file mode 100644 index 000000000..4b2f9f3b6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/package-info.java @@ -0,0 +1,4 @@ +/** + * MES 日历排班(Calendar / Shift Planning):班次、班组、班组成员、排班计划、假期设置等生产人员轮班与工作日历 + */ +package cn.iocoder.yudao.module.mes.controller.admin.cal; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanController.java new file mode 100644 index 000000000..5a1a782a5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.cal.plan.vo.MesCalPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 排班计划") +@RestController +@RequestMapping("/mes/cal/plan") +@Validated +public class MesCalPlanController { + + @Resource + private MesCalPlanService planService; + + @PostMapping("/create") + @Operation(summary = "创建排班计划") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:create')") + public CommonResult createPlan(@Valid @RequestBody MesCalPlanSaveReqVO createReqVO) { + return success(planService.createPlan(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新排班计划") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')") + public CommonResult updatePlan(@Valid @RequestBody MesCalPlanSaveReqVO updateReqVO) { + planService.updatePlan(updateReqVO); + return success(true); + } + + @PutMapping("/confirm") + @Operation(summary = "确认排班计划") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')") + public CommonResult confirmPlan(@RequestParam("id") Long id) { + planService.confirmPlan(id); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除排班计划") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-plan:delete')") + public CommonResult deletePlan(@RequestParam("id") Long id) { + planService.deletePlan(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得排班计划") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')") + public CommonResult getPlan(@RequestParam("id") Long id) { + MesCalPlanDO plan = planService.getPlan(id); + return success(BeanUtils.toBean(plan, MesCalPlanRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得排班计划分页") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')") + public CommonResult> getPlanPage(@Valid MesCalPlanPageReqVO pageReqVO) { + PageResult pageResult = planService.getPlanPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesCalPlanRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出排班计划 Excel") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportPlanExcel(@Valid MesCalPlanPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = planService.getPlanPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "排班计划.xls", "数据", MesCalPlanRespVO.class, + BeanUtils.toBean(list, MesCalPlanRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanShiftController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanShiftController.java new file mode 100644 index 000000000..1f6013e8f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanShiftController.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 计划班次") +@RestController +@RequestMapping("/mes/cal/plan-shift") +@Validated +public class MesCalPlanShiftController { + + @Resource + private MesCalPlanShiftService planShiftService; + + @PostMapping("/create") + @Operation(summary = "创建计划班次") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')") + public CommonResult createPlanShift(@Valid @RequestBody MesCalPlanShiftSaveReqVO createReqVO) { + return success(planShiftService.createPlanShift(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新计划班次") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')") + public CommonResult updatePlanShift(@Valid @RequestBody MesCalPlanShiftSaveReqVO updateReqVO) { + planShiftService.updatePlanShift(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除计划班次") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')") + public CommonResult deletePlanShift(@RequestParam("id") Long id) { + planShiftService.deletePlanShift(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得计划班次") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')") + public CommonResult getPlanShift(@RequestParam("id") Long id) { + MesCalPlanShiftDO planShift = planShiftService.getPlanShift(id); + return success(BeanUtils.toBean(planShift, MesCalPlanShiftRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得计划班次分页") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')") + public CommonResult> getPlanShiftPage(@Valid MesCalPlanShiftPageReqVO pageReqVO) { + PageResult pageResult = planShiftService.getPlanShiftPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesCalPlanShiftRespVO.class)); + } + + @GetMapping("/list-by-plan") + @Operation(summary = "获得指定排班计划的班次列表") + @Parameter(name = "planId", description = "排班计划编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')") + public CommonResult> getPlanShiftListByPlan(@RequestParam("planId") Long planId) { + List list = planShiftService.getPlanShiftListByPlanId(planId); + return success(BeanUtils.toBean(list, MesCalPlanShiftRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanTeamController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanTeamController.java new file mode 100644 index 000000000..7170ac531 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanTeamController.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanTeamService; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - MES 计划班组关联") +@RestController +@RequestMapping("/mes/cal/plan-team") +@Validated +public class MesCalPlanTeamController { + + @Resource + private MesCalPlanTeamService planTeamService; + @Resource + private MesCalTeamService teamService; + + @PostMapping("/create") + @Operation(summary = "创建计划班组关联") + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')") + public CommonResult createPlanTeam(@Valid @RequestBody MesCalPlanTeamSaveReqVO createReqVO) { + return success(planTeamService.createPlanTeam(createReqVO)); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除计划班组关联") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')") + public CommonResult deletePlanTeam(@RequestParam("id") Long id) { + planTeamService.deletePlanTeam(id); + return success(true); + } + + @GetMapping("/list-by-plan") + @Operation(summary = "获得指定排班计划的班组列表") + @Parameter(name = "planId", description = "排班计划编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')") + public CommonResult> getPlanTeamListByPlan(@RequestParam("planId") Long planId) { + List list = planTeamService.getPlanTeamListByPlanId(planId); + List respList = BeanUtils.toBean(list, MesCalPlanTeamRespVO.class); + // 拼装班组编码/名称 + // TODO @AI:if return + if (CollUtil.isNotEmpty(respList)) { + Map teamMap = teamService.getTeamMap( + convertList(respList, MesCalPlanTeamRespVO::getTeamId)); + respList.forEach(resp -> { + // TODO @AI:findand then + MesCalTeamDO team = teamMap.get(resp.getTeamId()); + if (team != null) { + resp.setTeamCode(team.getCode()).setTeamName(team.getName()); + } + }); + } + return success(respList); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanPageReqVO.java new file mode 100644 index 000000000..b88ef25b1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanPageReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 排班计划分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesCalPlanPageReqVO extends PageParam { + + @Schema(description = "计划编码", example = "PLAN001") + private String code; + + @Schema(description = "计划名称", example = "2024年排班") + private String name; + + @Schema(description = "轮班方式", example = "1") + private Integer shiftType; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "班组类型", example = "1") + private Integer calendarType; + + @Schema(description = "开始日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] startDate; + + @Schema(description = "结束日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] endDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java new file mode 100644 index 000000000..d68086899 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 排班计划 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesCalPlanRespVO { + + @Schema(description = "计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("计划编号") + private Long id; + + @Schema(description = "计划编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PLAN001") + @ExcelProperty("计划编码") + private String code; + + @Schema(description = "计划名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024年排班计划") + @ExcelProperty("计划名称") + private String name; + + @Schema(description = "班组类型", example = "1") + @ExcelProperty("班组类型") + private Integer calendarType; + + @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("开始日期") + private LocalDateTime startDate; + + @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("结束日期") + private LocalDateTime endDate; + + @Schema(description = "轮班方式", example = "1") + @ExcelProperty("轮班方式") + private Integer shiftType; + + @Schema(description = "倒班方式", example = "1") + @ExcelProperty("倒班方式") + private Integer shiftMethod; + + @Schema(description = "倒班天数", example = "7") + @ExcelProperty("倒班天数") + private Integer shiftCount; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanSaveReqVO.java new file mode 100644 index 000000000..4de150128 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanSaveReqVO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 排班计划新增/修改 Request VO") +@Data +public class MesCalPlanSaveReqVO { + + @Schema(description = "计划编号", example = "1024") + private Long id; + + @Schema(description = "计划编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PLAN001") + @NotEmpty(message = "计划编码不能为空") + private String code; + + @Schema(description = "计划名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024年排班计划") + @NotEmpty(message = "计划名称不能为空") + private String name; + + @Schema(description = "班组类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "班组类型不能为空") + private Integer calendarType; + + @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "开始日期不能为空") + private LocalDateTime startDate; + + @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "结束日期不能为空") + private LocalDateTime endDate; + + @Schema(description = "轮班方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "轮班方式不能为空") + private Integer shiftType; + + @Schema(description = "倒班方式", example = "1") + private Integer shiftMethod; + + @Schema(description = "倒班天数", example = "7") + private Integer shiftCount; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftPageReqVO.java new file mode 100644 index 000000000..525e16856 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 计划班次分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesCalPlanShiftPageReqVO extends PageParam { + + @Schema(description = "排班计划编号", example = "1") + private Long planId; + + @Schema(description = "班次名称", example = "白班") + private String name; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftRespVO.java new file mode 100644 index 000000000..c0613a95f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftRespVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 计划班次 Response VO") +@Data +public class MesCalPlanShiftRespVO { + + @Schema(description = "班次编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long planId; + + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sort; + + @Schema(description = "班次名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "白班") + private String name; + + @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "08:00") + private String startTime; + + @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "17:00") + private String endTime; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftSaveReqVO.java new file mode 100644 index 000000000..cf2cefbf9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalPlanShiftSaveReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 计划班次新增/修改 Request VO") +@Data +public class MesCalPlanShiftSaveReqVO { + + @Schema(description = "班次编号", example = "1024") + private Long id; + + @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "排班计划不能为空") + private Long planId; + + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "显示顺序不能为空") + private Integer sort; + + @Schema(description = "班次名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "白班") + @NotEmpty(message = "班次名称不能为空") + private String name; + + @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "08:00") + @NotEmpty(message = "开始时间不能为空") + private String startTime; + + @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "17:00") + @NotEmpty(message = "结束时间不能为空") + private String endTime; + + @Schema(description = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamRespVO.java new file mode 100644 index 000000000..d2a0a0d95 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 计划班组关联 Response VO") +@Data +public class MesCalPlanTeamRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long planId; + + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long teamId; + + @Schema(description = "班组编码", example = "T001") + private String teamCode; + + @Schema(description = "班组名称", example = "A组") + private String teamName; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamSaveReqVO.java new file mode 100644 index 000000000..1ea116530 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamSaveReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 计划班组关联新增 Request VO") +@Data +public class MesCalPlanTeamSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "排班计划不能为空") + private Long planId; + + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "班组不能为空") + private Long teamId; + + @Schema(description = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamController.java new file mode 100644 index 000000000..5ba5108a3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamController.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.cal.team.vo.MesCalTeamPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 班组") +@RestController +@RequestMapping("/mes/cal/team") +@Validated +public class MesCalTeamController { + + @Resource + private MesCalTeamService teamService; + + @PostMapping("/create") + @Operation(summary = "创建班组") + @PreAuthorize("@ss.hasPermission('mes:cal-team:create')") + public CommonResult createTeam(@Valid @RequestBody MesCalTeamSaveReqVO createReqVO) { + return success(teamService.createTeam(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新班组") + @PreAuthorize("@ss.hasPermission('mes:cal-team:update')") + public CommonResult updateTeam(@Valid @RequestBody MesCalTeamSaveReqVO updateReqVO) { + teamService.updateTeam(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除班组") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-team:delete')") + public CommonResult deleteTeam(@RequestParam("id") Long id) { + teamService.deleteTeam(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得班组") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:cal-team:query')") + public CommonResult getTeam(@RequestParam("id") Long id) { + MesCalTeamDO team = teamService.getTeam(id); + return success(BeanUtils.toBean(team, MesCalTeamRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得班组分页") + @PreAuthorize("@ss.hasPermission('mes:cal-team:query')") + public CommonResult> getTeamPage(@Valid MesCalTeamPageReqVO pageReqVO) { + PageResult pageResult = teamService.getTeamPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesCalTeamRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得班组列表") + @PreAuthorize("@ss.hasPermission('mes:cal-team:query')") + public CommonResult> getTeamList() { + List list = teamService.getTeamList(); + return success(BeanUtils.toBean(list, MesCalTeamRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出班组 Excel") + @PreAuthorize("@ss.hasPermission('mes:cal-team:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTeamExcel(@Valid MesCalTeamPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = teamService.getTeamPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "班组.xls", "数据", MesCalTeamRespVO.class, + BeanUtils.toBean(list, MesCalTeamRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamMemberController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamMemberController.java new file mode 100644 index 000000000..78bc15d9c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamMemberController.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamMemberService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 班组成员") +@RestController +@RequestMapping("/mes/cal/team-member") +@Validated +public class MesCalTeamMemberController { + + @Resource + private MesCalTeamMemberService teamMemberService; + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建班组成员") + @PreAuthorize("@ss.hasPermission('mes:cal-team:create')") + public CommonResult createTeamMember(@Valid @RequestBody MesCalTeamMemberSaveReqVO createReqVO) { + return success(teamMemberService.createTeamMember(createReqVO)); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除班组成员") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:cal-team:delete')") + public CommonResult deleteTeamMember(@RequestParam("id") Long id) { + teamMemberService.deleteTeamMember(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得班组成员") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:cal-team:query')") + public CommonResult getTeamMember(@RequestParam("id") Long id) { + MesCalTeamMemberDO member = teamMemberService.getTeamMember(id); + return success(BeanUtils.toBean(member, MesCalTeamMemberRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得班组成员分页") + @PreAuthorize("@ss.hasPermission('mes:cal-team:query')") + public CommonResult> getTeamMemberPage(@Valid MesCalTeamMemberPageReqVO pageReqVO) { + PageResult pageResult = teamMemberService.getTeamMemberPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesCalTeamMemberRespVO.class)); + } + + @GetMapping("/list-by-team") + @Operation(summary = "获得班组成员列表", description = "支持单个 teamId 或多个 teamIds") + @PreAuthorize("@ss.hasPermission('mes:cal-team:query')") + public CommonResult> getTeamMemberListByTeam( + @RequestParam(value = "teamId", required = false) Long teamId, + @RequestParam(value = "teamIds", required = false) Collection teamIds) { + List list; + if (CollUtil.isNotEmpty(teamIds)) { + list = teamMemberService.getTeamMemberListByTeamIds(teamIds); + } else if (teamId != null) { + list = teamMemberService.getTeamMemberListByTeamId(teamId); + } else { + list = Collections.emptyList(); + } + return success(buildMemberRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildMemberRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesCalTeamMemberDO::getUserId)); + return BeanUtils.toBean(list, MesCalTeamMemberRespVO.class, vo -> + MapUtils.findAndThen(userMap, vo.getUserId(), user -> { + vo.setNickname(user.getNickname()); + vo.setTelephone(user.getMobile()); + })); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamShiftController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamShiftController.java new file mode 100644 index 000000000..165aa76fa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/MesCalTeamShiftController.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 班组排班") +@RestController +@RequestMapping("/mes/cal/team-shift") +@Validated +public class MesCalTeamShiftController { + + @Resource + private MesCalTeamShiftService teamShiftService; + @Resource + private MesCalTeamService teamService; + @Resource + private MesCalPlanShiftService planShiftService; + + @GetMapping("/list") + @Operation(summary = "获得班组排班列表") + @PreAuthorize("@ss.hasPermission('mes:cal-team-shift:query')") + public CommonResult> getTeamShiftList(@Valid MesCalTeamShiftListReqVO reqVO) { + List list = teamShiftService.getTeamShiftList(reqVO); + if (CollUtil.isEmpty(list)) { + return success(Collections.emptyList()); + } + // 关联查询班组名称和班次名称 + Map teamMap = teamService.getTeamMap( + convertSet(list, MesCalTeamShiftDO::getTeamId)); + Map shiftMap = planShiftService.getPlanShiftMap( + convertSet(list, MesCalTeamShiftDO::getShiftId)); + return success(BeanUtils.toBean(list, MesCalTeamShiftRespVO.class, vo -> { + MapUtils.findAndThen(teamMap, vo.getTeamId(), team -> vo.setTeamName(team.getName())); + MapUtils.findAndThen(shiftMap, vo.getShiftId(), shift -> vo.setShiftName(shift.getName())); + })); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamPageReqVO.java new file mode 100644 index 000000000..ddc36812f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 班组分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesCalTeamPageReqVO extends PageParam { + + @Schema(description = "班组编码", example = "TEAM-A") + private String code; + + @Schema(description = "班组名称", example = "注塑") + private String name; + + @Schema(description = "班组类型", example = "1") + private Integer calendarType; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java new file mode 100644 index 000000000..27d411755 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 班组 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesCalTeamRespVO { + + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("班组编号") + private Long id; + + @Schema(description = "班组编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "TEAM-A") + @ExcelProperty("班组编码") + private String code; + + @Schema(description = "班组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑A组") + @ExcelProperty("班组名称") + private String name; + + @Schema(description = "班组类型", example = "1") + @ExcelProperty("班组类型") + private Integer calendarType; + + @Schema(description = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamSaveReqVO.java new file mode 100644 index 000000000..e2f10f93f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamSaveReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 班组新增/修改 Request VO") +@Data +public class MesCalTeamSaveReqVO { + + @Schema(description = "班组编号", example = "1024") + private Long id; + + @Schema(description = "班组编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "TEAM-A") + @NotEmpty(message = "班组编码不能为空") + private String code; + + @Schema(description = "班组名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑A组") + @NotEmpty(message = "班组名称不能为空") + private String name; + + @Schema(description = "班组类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "班组类型不能为空") + private Integer calendarType; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberPageReqVO.java new file mode 100644 index 000000000..c225375c8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberPageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 班组成员分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesCalTeamMemberPageReqVO extends PageParam { + + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "201") + @NotNull(message = "班组编号不能为空") + private Long teamId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberRespVO.java new file mode 100644 index 000000000..023538bbc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 班组成员 Response VO") +@Data +public class MesCalTeamMemberRespVO { + + @Schema(description = "班组成员编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "201") + private Long teamId; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long userId; + + @Schema(description = "用户昵称", example = "管理员") + private String nickname; + + @Schema(description = "电话", example = "13800138000") + private String telephone; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberSaveReqVO.java new file mode 100644 index 000000000..71a2658f2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/member/MesCalTeamMemberSaveReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 班组成员新增 Request VO") +@Data +public class MesCalTeamMemberSaveReqVO { + + @Schema(description = "班组成员编号", example = "1024") + private Long id; + + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "201") + @NotNull(message = "班组编号不能为空") + private Long teamId; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "用户编号不能为空") + private Long userId; + + @Schema(description = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftListReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftListReqVO.java new file mode 100644 index 000000000..459be38e8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftListReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; +import java.util.Collection; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 班组排班列表 Request VO") +@Data +public class MesCalTeamShiftListReqVO { + + @Schema(description = "班组编号", example = "201") + private Long teamId; + + @Schema(description = "班组编号集合") + private Collection teamIds; + + @Schema(description = "排班计划编号", example = "1") + private Long planId; + + @Schema(description = "开始日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime startDay; + + @Schema(description = "结束日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime endDay; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftRespVO.java new file mode 100644 index 000000000..a1af1bbb0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/shift/MesCalTeamShiftRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 班组排班 Response VO") +@Data +public class MesCalTeamShiftRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "排班计划编号", example = "1") + private Long planId; + + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "201") + private Long teamId; + + @Schema(description = "班组名称", example = "注塑A组") + private String teamName; + + @Schema(description = "班次编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long shiftId; + + @Schema(description = "班次名称", example = "白班") + private String shiftName; + + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime day; + + @Schema(description = "排序", example = "1") + private Integer sort; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanController.java new file mode 100644 index 000000000..55872f11a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanController.java @@ -0,0 +1,111 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.dv.checkplan.vo.MesDvCheckPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 点检保养方案") +@RestController +@RequestMapping("/mes/dv/check-plan") +@Validated +public class MesDvCheckPlanController { + + @Resource + private MesDvCheckPlanService checkPlanService; + + @PostMapping("/create") + @Operation(summary = "创建点检保养方案") + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:create')") + public CommonResult createCheckPlan(@Valid @RequestBody MesDvCheckPlanSaveReqVO createReqVO) { + return success(checkPlanService.createCheckPlan(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新点检保养方案") + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')") + public CommonResult updateCheckPlan(@Valid @RequestBody MesDvCheckPlanSaveReqVO updateReqVO) { + checkPlanService.updateCheckPlan(updateReqVO); + return success(true); + } + + @PutMapping("/enable") + @Operation(summary = "启用点检保养方案") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')") + public CommonResult enableCheckPlan(@RequestParam("id") Long id) { + checkPlanService.enableCheckPlan(id); + return success(true); + } + + @PutMapping("/disable") + @Operation(summary = "停用点检保养方案") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')") + public CommonResult disableCheckPlan(@RequestParam("id") Long id) { + checkPlanService.disableCheckPlan(id); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除点检保养方案") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:delete')") + public CommonResult deleteCheckPlan(@RequestParam("id") Long id) { + checkPlanService.deleteCheckPlan(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得点检保养方案") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:query')") + public CommonResult getCheckPlan(@RequestParam("id") Long id) { + MesDvCheckPlanDO checkPlan = checkPlanService.getCheckPlan(id); + return success(BeanUtils.toBean(checkPlan, MesDvCheckPlanRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得点检保养方案分页") + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:query')") + public CommonResult> getCheckPlanPage(@Valid MesDvCheckPlanPageReqVO pageReqVO) { + PageResult pageResult = checkPlanService.getCheckPlanPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesDvCheckPlanRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出点检保养方案 Excel") + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportCheckPlanExcel(@Valid MesDvCheckPlanPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = checkPlanService.getCheckPlanPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "点检保养方案.xls", "数据", MesDvCheckPlanRespVO.class, + BeanUtils.toBean(list, MesDvCheckPlanRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java new file mode 100644 index 000000000..ef7a3d011 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery.MesDvCheckPlanMachineryRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery.MesDvCheckPlanMachinerySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanMachineryDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanMachineryService; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 点检保养方案设备") +@RestController +@RequestMapping("/mes/dv/check-plan-machinery") +@Validated +public class MesDvCheckPlanMachineryController { + + @Resource + private MesDvCheckPlanMachineryService checkPlanMachineryService; + @Resource + private MesDvMachineryService machineryService; + + @PostMapping("/create") + @Operation(summary = "创建方案设备关联") + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')") + public CommonResult createCheckPlanMachinery(@Valid @RequestBody MesDvCheckPlanMachinerySaveReqVO createReqVO) { + return success(checkPlanMachineryService.createCheckPlanMachinery(createReqVO)); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除方案设备关联") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')") + public CommonResult deleteCheckPlanMachinery(@RequestParam("id") Long id) { + checkPlanMachineryService.deleteCheckPlanMachinery(id); + return success(true); + } + + @GetMapping("/list-by-plan") + @Operation(summary = "获得指定方案的设备列表") + @Parameter(name = "planId", description = "方案编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:query')") + public CommonResult> getCheckPlanMachineryListByPlan( + @RequestParam("planId") Long planId) { + List list = checkPlanMachineryService.getCheckPlanMachineryListByPlanId(planId); + return success(buildCheckPlanMachineryRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildCheckPlanMachineryRespVOList( + List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + Map machineryMap = machineryService.getMachineryMap( + convertSet(list, MesDvCheckPlanMachineryDO::getMachineryId)); + return BeanUtils.toBean(list, MesDvCheckPlanMachineryRespVO.class, vo -> + MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> + vo.setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName()) + .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec()) + ) + ); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanSubjectController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanSubjectController.java new file mode 100644 index 000000000..ce0d56fd4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanSubjectController.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject.MesDvCheckPlanSubjectRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject.MesDvCheckPlanSubjectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanSubjectDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanSubjectService; +import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 点检保养方案项目") +@RestController +@RequestMapping("/mes/dv/check-plan-subject") +@Validated +public class MesDvCheckPlanSubjectController { + + @Resource + private MesDvCheckPlanSubjectService checkPlanSubjectService; + @Resource + private MesDvSubjectService subjectService; + + @PostMapping("/create") + @Operation(summary = "创建方案项目关联") + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')") + public CommonResult createCheckPlanSubject(@Valid @RequestBody MesDvCheckPlanSubjectSaveReqVO createReqVO) { + return success(checkPlanSubjectService.createCheckPlanSubject(createReqVO)); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除方案项目关联") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:update')") + public CommonResult deleteCheckPlanSubject(@RequestParam("id") Long id) { + checkPlanSubjectService.deleteCheckPlanSubject(id); + return success(true); + } + + @GetMapping("/list-by-plan") + @Operation(summary = "获得指定方案的项目列表") + @Parameter(name = "planId", description = "方案编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-plan:query')") + public CommonResult> getCheckPlanSubjectListByPlan( + @RequestParam("planId") Long planId) { + List list = checkPlanSubjectService.getCheckPlanSubjectListByPlanId(planId); + List respList = BeanUtils.toBean(list, MesDvCheckPlanSubjectRespVO.class); + // 拼装项目编码/名称/类型/内容/标准 + // MesDvCheckPlanMachineryController.java 参考下里面的 todo; + if (CollUtil.isNotEmpty(respList)) { + List subjectIds = CollectionUtils.convertList(respList, MesDvCheckPlanSubjectRespVO::getSubjectId); + Map subjectMap = subjectService.getSubjectMap(subjectIds); + respList.forEach(resp -> { + MesDvSubjectDO subject = subjectMap.get(resp.getSubjectId()); + if (subject != null) { + resp.setSubjectCode(subject.getCode()); + resp.setSubjectName(subject.getName()); + resp.setSubjectType(subject.getType()); + resp.setSubjectContent(subject.getContent()); + resp.setSubjectStandard(subject.getStandard()); + } + }); + } + return success(respList); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanPageReqVO.java new file mode 100644 index 000000000..c7c13196e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 点检保养方案分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvCheckPlanPageReqVO extends PageParam { + + @Schema(description = "方案编码", example = "CHP001") + private String code; + + @Schema(description = "方案名称", example = "注塑机") + private String name; + + @Schema(description = "方案类型", example = "1") + private Integer type; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java new file mode 100644 index 000000000..ff9c79df7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 点检保养方案 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvCheckPlanRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "方案编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CHP001") + @ExcelProperty("方案编码") + private String code; + + @Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑机日检方案") + @ExcelProperty("方案名称") + private String name; + + @Schema(description = "方案类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("方案类型") + private Integer type; + + @Schema(description = "开始日期") + @ExcelProperty("开始日期") + private LocalDateTime startDate; + + @Schema(description = "结束日期") + @ExcelProperty("结束日期") + private LocalDateTime endDate; + + @Schema(description = "周期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("周期类型") + private Integer cycleType; + + @Schema(description = "周期数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("周期数量") + private Integer cycleCount; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanSaveReqVO.java new file mode 100644 index 000000000..fe4832e58 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanSaveReqVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 点检保养方案新增/修改 Request VO") +@Data +public class MesDvCheckPlanSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "方案编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CHP001") + @NotEmpty(message = "方案编码不能为空") + private String code; + + @Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑机日检方案") + @NotEmpty(message = "方案名称不能为空") + private String name; + + @Schema(description = "方案类型(1=设备点检,2=设备保养)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "方案类型不能为空") + private Integer type; + + @Schema(description = "开始日期") + private LocalDateTime startDate; + + @Schema(description = "结束日期") + private LocalDateTime endDate; + + @Schema(description = "周期类型(1=天,2=周,3=月,4=年)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "周期类型不能为空") + private Integer cycleType; + + @Schema(description = "周期数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "周期数量不能为空") + private Integer cycleCount; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java new file mode 100644 index 000000000..0d2b74267 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 点检保养方案设备 Response VO") +@Data +public class MesDvCheckPlanMachineryRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long planId; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long machineryId; + + @Schema(description = "设备编码", example = "EQ001") + private String machineryCode; + + @Schema(description = "设备名称", example = "注塑机A") + private String machineryName; + + @Schema(description = "品牌", example = "海天") + private String machineryBrand; + + @Schema(description = "规格型号", example = "HTF120") + private String machinerySpec; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachinerySaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachinerySaveReqVO.java new file mode 100644 index 000000000..8a0bc036b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachinerySaveReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 点检保养方案设备新增 Request VO") +@Data +public class MesDvCheckPlanMachinerySaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "方案编号不能为空") + private Long planId; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "设备不能为空") + private Long machineryId; + + @Schema(description = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectRespVO.java new file mode 100644 index 000000000..545700678 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 点检保养方案项目 Response VO") +@Data +public class MesDvCheckPlanSubjectRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long planId; + + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long subjectId; + + @Schema(description = "项目编码", example = "CHK001") + private String subjectCode; + + @Schema(description = "项目名称", example = "油温检查") + private String subjectName; + + @Schema(description = "项目类型", example = "1") + private Integer subjectType; + + @Schema(description = "项目内容", example = "检查油温是否正常") + private String subjectContent; + + @Schema(description = "标准", example = "40-60°C") + private String subjectStandard; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectSaveReqVO.java new file mode 100644 index 000000000..ad633a3d4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/subject/MesDvCheckPlanSubjectSaveReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 点检保养方案项目新增 Request VO") +@Data +public class MesDvCheckPlanSubjectSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "方案编号不能为空") + private Long planId; + + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "点检保养项目不能为空") + private Long subjectId; + + @Schema(description = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java new file mode 100644 index 000000000..d6b55292e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java @@ -0,0 +1,152 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.dv.checkrecord.vo.MesDvCheckRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; +import cn.iocoder.yudao.module.mes.service.dv.checkrecord.MesDvCheckRecordService; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 设备点检记录") +@RestController +@RequestMapping("/mes/dv/check-record") +@Validated +public class MesDvCheckRecordController { + + @Resource + private MesDvCheckRecordService checkRecordService; + + @Resource + private MesDvCheckPlanService checkPlanService; + + @Resource + private MesDvMachineryService machineryService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建设备点检记录") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:create')") + public CommonResult createCheckRecord(@Valid @RequestBody MesDvCheckRecordSaveReqVO createReqVO) { + return success(checkRecordService.createCheckRecord(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新设备点检记录") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:update')") + public CommonResult updateCheckRecord(@Valid @RequestBody MesDvCheckRecordSaveReqVO updateReqVO) { + checkRecordService.updateCheckRecord(updateReqVO); + return success(true); + } + + @PutMapping("/submit") + @Operation(summary = "提交设备点检记录(草稿→已完成)") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:update')") + public CommonResult submitCheckRecord(@RequestParam("id") Long id) { + checkRecordService.submitCheckRecord(id); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除设备点检记录") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:delete')") + public CommonResult deleteCheckRecord(@RequestParam("id") Long id) { + checkRecordService.deleteCheckRecord(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得设备点检记录") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:query')") + public CommonResult getCheckRecord(@RequestParam("id") Long id) { + MesDvCheckRecordDO checkRecord = checkRecordService.getCheckRecord(id); + if (checkRecord == null) { + return success(null); + } + return success(buildCheckRecordRespVOList(Collections.singletonList(checkRecord)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得设备点检记录分页") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:query')") + public CommonResult> getCheckRecordPage(@Valid MesDvCheckRecordPageReqVO pageReqVO) { + PageResult pageResult = checkRecordService.getCheckRecordPage(pageReqVO); + return success(new PageResult<>(buildCheckRecordRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出设备点检记录 Excel") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportCheckRecordExcel(@Valid MesDvCheckRecordPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = checkRecordService.getCheckRecordPage(pageReqVO).getList(); + ExcelUtils.write(response, "设备点检记录.xls", "数据", MesDvCheckRecordRespVO.class, + buildCheckRecordRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + @SuppressWarnings("DuplicatedCode") + private List buildCheckRecordRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map planMap = checkPlanService.getCheckPlanMap( + convertSet(list, MesDvCheckRecordDO::getPlanId)); + Map machineryMap = machineryService.getMachineryMap( + convertSet(list, MesDvCheckRecordDO::getMachineryId)); + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesDvCheckRecordDO::getUserId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesDvCheckRecordRespVO.class, vo -> { + MapUtils.findAndThen(planMap, vo.getPlanId(), + plan -> vo.setPlanName(plan.getName()).setPlanCode(plan.getCode()) + .setPlanStartDate(plan.getStartDate()).setPlanEndDate(plan.getEndDate()) + .setPlanCycleType(plan.getCycleType()).setPlanCycleCount(plan.getCycleCount())); + MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo + .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName()) + .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec())); + MapUtils.findAndThen(userMap, vo.getUserId(), + user -> vo.setNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordLineController.java new file mode 100644 index 000000000..95e61d2fd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordLineController.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import cn.iocoder.yudao.module.mes.service.dv.checkrecord.MesDvCheckRecordLineService; +import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 设备点检记录明细") +@RestController +@RequestMapping("/mes/dv/check-record-line") +@Validated +public class MesDvCheckRecordLineController { + + @Resource + private MesDvCheckRecordLineService checkRecordLineService; + + @Resource + private MesDvSubjectService subjectService; + + @PostMapping("/create") + @Operation(summary = "创建设备点检记录明细") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:create')") + public CommonResult createCheckRecordLine(@Valid @RequestBody MesDvCheckRecordLineSaveReqVO createReqVO) { + return success(checkRecordLineService.createCheckRecordLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新设备点检记录明细") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:update')") + public CommonResult updateCheckRecordLine(@Valid @RequestBody MesDvCheckRecordLineSaveReqVO updateReqVO) { + checkRecordLineService.updateCheckRecordLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除设备点检记录明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:delete')") + public CommonResult deleteCheckRecordLine(@RequestParam("id") Long id) { + checkRecordLineService.deleteCheckRecordLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得设备点检记录明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:query')") + public CommonResult getCheckRecordLine(@RequestParam("id") Long id) { + MesDvCheckRecordLineDO line = checkRecordLineService.getCheckRecordLine(id); + if (line == null) { + return success(null); + } + return success(buildCheckRecordLineRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得设备点检记录明细分页") + @PreAuthorize("@ss.hasPermission('mes:dv-check-record:query')") + public CommonResult> getCheckRecordLinePage(@Valid MesDvCheckRecordLinePageReqVO pageReqVO) { + PageResult pageResult = checkRecordLineService.getCheckRecordLinePage(pageReqVO); + return success(new PageResult<>(buildCheckRecordLineRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildCheckRecordLineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map subjectMap = subjectService.getSubjectMap( + convertSet(list, MesDvCheckRecordLineDO::getSubjectId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesDvCheckRecordLineRespVO.class, vo -> + MapUtils.findAndThen(subjectMap, vo.getSubjectId(), subject -> vo + .setSubjectCode(subject.getCode()).setSubjectName(subject.getName()) + .setSubjectType(subject.getType()).setSubjectContent(subject.getContent()).setSubjectStandard(subject.getStandard()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordPageReqVO.java new file mode 100644 index 000000000..340a2a21c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 设备点检记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvCheckRecordPageReqVO extends PageParam { + + @Schema(description = "点检计划编号", example = "1") + private Long planId; + + @Schema(description = "设备编号", example = "1") + private Long machineryId; + + @Schema(description = "点检人编号", example = "1") + private Long userId; + + @Schema(description = "状态", example = "10") + private Integer status; + + @Schema(description = "点检时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] checkTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java new file mode 100644 index 000000000..857d9dc10 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备点检记录 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvCheckRecordRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "点检计划编号", example = "1") + private Long planId; + + @Schema(description = "计划名称", example = "日常点检计划") + @ExcelProperty("计划名称") + private String planName; + + @Schema(description = "计划编码", example = "P001") + @ExcelProperty("计划编码") + private String planCode; + + @Schema(description = "开始时间") + @ExcelProperty("开始时间") + private LocalDateTime planStartDate; + + @Schema(description = "结束日期") + @ExcelProperty("结束日期") + private LocalDateTime planEndDate; + + @Schema(description = "频率类型", example = "1") + @ExcelProperty(value = "频率类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_CYCLE_TYPE) + private Integer planCycleType; + + @Schema(description = "频率数量", example = "5") + @ExcelProperty(value = "频率数量") + private Integer planCycleCount; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long machineryId; + + @Schema(description = "设备编码", example = "M001") + @ExcelProperty("设备编码") + private String machineryCode; + + @Schema(description = "设备名称", example = "机床A") + @ExcelProperty("设备名称") + private String machineryName; + + @Schema(description = "品牌", example = "西门子") + @ExcelProperty("品牌") + private String machineryBrand; + + @Schema(description = "规格型号", example = "X-100") + @ExcelProperty("规格型号") + private String machinerySpec; + + @Schema(description = "点检时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("点检时间") + private LocalDateTime checkTime; + + @Schema(description = "点检人编号", example = "1") + private Long userId; + + @Schema(description = "点检人名称", example = "张三") + @ExcelProperty("点检人") + private String nickname; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_CHECK_RECORD_STATUS) + private Integer status; + + @Schema(description = "备注", example = "测试备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordSaveReqVO.java new file mode 100644 index 000000000..3abbc1bac --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备点检记录新增/修改 Request VO") +@Data +public class MesDvCheckRecordSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024") + private Long id; + + @Schema(description = "点检计划编号", example = "1") + private Long planId; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "设备不能为空") + private Long machineryId; + + @Schema(description = "点检时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "点检时间不能为空") + private LocalDateTime checkTime; + + @Schema(description = "点检人编号", example = "1") + private Long userId; + + @Schema(description = "备注", example = "测试备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLinePageReqVO.java new file mode 100644 index 000000000..166fc553e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLinePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 设备点检记录明细分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvCheckRecordLinePageReqVO extends PageParam { + + @Schema(description = "点检记录编号", example = "1") + private Long recordId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java new file mode 100644 index 000000000..27a90ab76 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备点检记录明细 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvCheckRecordLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "点检记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long recordId; + + @Schema(description = "点检项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long subjectId; + + @Schema(description = "项目编码", example = "S001") + @ExcelProperty("项目编码") + private String subjectCode; + + @Schema(description = "项目名称", example = "润滑油检查") + @ExcelProperty("项目名称") + private String subjectName; + + @Schema(description = "项目类型", example = "1") + @ExcelProperty("项目类型") + private Integer subjectType; + + @Schema(description = "检查内容", example = "检查润滑油是否充足") + @ExcelProperty("检查内容") + private String subjectContent; + + @Schema(description = "检查标准", example = "油位不低于最低刻度") + @ExcelProperty("检查标准") + private String subjectStandard; + + @Schema(description = "点检结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "点检结果", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_CHECK_RESULT) + private Integer checkStatus; + + @Schema(description = "异常描述", example = "设备异响") + @ExcelProperty("异常描述") + private String checkResult; + + @Schema(description = "备注", example = "测试备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineSaveReqVO.java new file mode 100644 index 000000000..9ece0852a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +@Schema(description = "管理后台 - MES 设备点检记录明细新增/修改 Request VO") +@Data +public class MesDvCheckRecordLineSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024") + private Long id; + + @Schema(description = "点检记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "点检记录不能为空") + private Long recordId; + + @Schema(description = "点检项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "点检项目不能为空") + private Long subjectId; + + @Schema(description = "点检结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "点检结果不能为空") + private Integer checkStatus; + + @Schema(description = "异常描述", example = "设备异响") + private String checkResult; + + @Schema(description = "备注", example = "测试备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java new file mode 100644 index 000000000..e6d89e54d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java @@ -0,0 +1,170 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.dv.machinery.vo.MesDvMachineryImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachinerySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryTypeService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkshopService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 设备台账") +@RestController +@RequestMapping("/mes/dv/machinery") +@Validated +public class MesDvMachineryController { + + @Resource + private MesDvMachineryService machineryService; + + @Resource + private MesDvMachineryTypeService machineryTypeService; + + @Resource + private MesMdWorkshopService workshopService; + + @PostMapping("/create") + @Operation(summary = "创建设备") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery:create')") + public CommonResult createMachinery(@Valid @RequestBody MesDvMachinerySaveReqVO createReqVO) { + return success(machineryService.createMachinery(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新设备") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery:update')") + public CommonResult updateMachinery(@Valid @RequestBody MesDvMachinerySaveReqVO updateReqVO) { + machineryService.updateMachinery(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除设备") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-machinery:delete')") + public CommonResult deleteMachinery(@RequestParam("id") Long id) { + machineryService.deleteMachinery(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得设备") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery:query')") + public CommonResult getMachinery(@RequestParam("id") Long id) { + MesDvMachineryDO machinery = machineryService.getMachinery(id); + if (machinery == null) { + return success(null); + } + return success(buildMachineryRespVOList(Collections.singletonList(machinery)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得设备分页") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery:query')") + public CommonResult> getMachineryPage(@Valid MesDvMachineryPageReqVO pageReqVO) { + PageResult pageResult = machineryService.getMachineryPage(pageReqVO); + return success(new PageResult<>(buildMachineryRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出设备 Excel") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportMachineryExcel(@Valid MesDvMachineryPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = machineryService.getMachineryPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "设备台账.xls", "数据", MesDvMachineryRespVO.class, + buildMachineryRespVOList(list)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得设备精简列表", description = "主要用于前端的下拉选项") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery:query')") + public CommonResult> getMachinerySimpleList() { + List list = machineryService.getMachineryList(); + return success(BeanUtils.toBean(list, MesDvMachineryRespVO.class)); + } + + @GetMapping("/get-import-template") + @Operation(summary = "获得设备导入模板") + public void importTemplate(HttpServletResponse response) throws IOException { + // 手动创建导出 demo + List list = Collections.singletonList( + MesDvMachineryImportExcelVO.builder().code("EQ-001").name("示例设备") + .brand("示例品牌").spec("型号A").machineryTypeCode("MT-001") + .workshopCode("WS-001").status(0).build() + ); + // 输出 + ExcelUtils.write(response, "设备导入模板.xls", "设备列表", MesDvMachineryImportExcelVO.class, list); + } + + @PostMapping("/import") + @Operation(summary = "导入设备") + @Parameters({ + @Parameter(name = "file", description = "Excel 文件", required = true), + @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") + }) + @PreAuthorize("@ss.hasPermission('mes:dv-machinery:import')") + public CommonResult importExcel(@RequestParam("file") MultipartFile file, + @RequestParam(value = "updateSupport", required = false, + defaultValue = "false") Boolean updateSupport) throws Exception { + List list = ExcelUtils.read(file, MesDvMachineryImportExcelVO.class); + return success(machineryService.importMachineryList(list, updateSupport)); + } + + // ==================== 拼接 VO ==================== + + private List buildMachineryRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取设备类型和车间信息 + Map machineryTypeMap = machineryTypeService.getMachineryTypeMap( + convertSet(list, MesDvMachineryDO::getMachineryTypeId)); + Map workshopMap = workshopService.getWorkshopMap( + convertSet(list, MesDvMachineryDO::getWorkshopId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesDvMachineryRespVO.class, vo -> { + MapUtils.findAndThen(machineryTypeMap, vo.getMachineryTypeId(), + machineryType -> vo.setMachineryTypeName(machineryType.getName())); + MapUtils.findAndThen(workshopMap, vo.getWorkshopId(), + workshop -> vo.setWorkshopName(workshop.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryTypeController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryTypeController.java new file mode 100644 index 000000000..e534d76a9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryTypeController.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - MES 设备类型") +@RestController +@RequestMapping("/mes/dv/machinery-type") +@Validated +public class MesDvMachineryTypeController { + + @Resource + private MesDvMachineryTypeService machineryTypeService; + + @PostMapping("/create") + @Operation(summary = "创建设备类型") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:create')") + public CommonResult createMachineryType(@Valid @RequestBody MesDvMachineryTypeSaveReqVO createReqVO) { + return success(machineryTypeService.createMachineryType(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新设备类型") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:update')") + public CommonResult updateMachineryType(@Valid @RequestBody MesDvMachineryTypeSaveReqVO updateReqVO) { + machineryTypeService.updateMachineryType(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除设备类型") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:delete')") + public CommonResult deleteMachineryType(@RequestParam("id") Long id) { + machineryTypeService.deleteMachineryType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得设备类型") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:query')") + public CommonResult getMachineryType(@RequestParam("id") Long id) { + MesDvMachineryTypeDO machineryType = machineryTypeService.getMachineryType(id); + return success(BeanUtils.toBean(machineryType, MesDvMachineryTypeRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得设备类型列表") + @PreAuthorize("@ss.hasPermission('mes:dv-machinery-type:query')") + public CommonResult> getMachineryTypeList(@Valid MesDvMachineryTypeListReqVO listReqVO) { + List list = machineryTypeService.getMachineryTypeList(listReqVO); + return success(BeanUtils.toBean(list, MesDvMachineryTypeRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得设备类型精简列表", description = "只包含被开启的类型,主要用于前端的下拉选项") + public CommonResult> getMachineryTypeSimpleList() { + List list = machineryTypeService.getMachineryTypeList( + new MesDvMachineryTypeListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + return success(convertList(list, machineryType -> new MesDvMachineryTypeRespVO() + .setId(machineryType.getId()).setName(machineryType.getName()).setParentId(machineryType.getParentId()) + .setCode(machineryType.getCode()).setRemark(machineryType.getRemark()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java new file mode 100644 index 000000000..64f8d824c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 设备台账 Excel 导入 VO + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MesDvMachineryImportExcelVO { + + @ExcelProperty("设备编码") + private String code; + + @ExcelProperty("设备名称") + private String name; + + @ExcelProperty("品牌") + private String brand; + + @ExcelProperty("规格型号") + private String spec; + + @ExcelProperty("设备类型编码") + private String machineryTypeCode; + + @ExcelProperty("所属车间编码") + private String workshopCode; + + @ExcelProperty(value = "设备状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_MACHINERY_STATUS) + private Integer status; + + @ExcelProperty("备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportRespVO.java new file mode 100644 index 000000000..aef4a69e0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Schema(description = "管理后台 - MES 设备台账导入 Response VO") +@Data +@Builder +public class MesDvMachineryImportRespVO { + + @Schema(description = "创建成功的设备编码数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List createCodes; + + @Schema(description = "更新成功的设备编码数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List updateCodes; + + @Schema(description = "导入失败的设备集合,key 为设备编码,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) + private Map failureCodes; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryPageReqVO.java new file mode 100644 index 000000000..aefad442e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryPageReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.Set; + +@Schema(description = "管理后台 - MES 设备台账分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvMachineryPageReqVO extends PageParam { + + @Schema(description = "设备编码", example = "EQ-001") + private String code; + + @Schema(description = "设备名称", example = "CNC 加工中心") + private String name; + + @Schema(description = "品牌", example = "西门子") + private String brand; + + @Schema(description = "设备类型编号", example = "100") + private Long machineryTypeId; + + @Schema(description = "设备类型编号列表(含子类型,由后端自动填充)", hidden = true) + private Set machineryTypeIds; + + @Schema(description = "所属车间编号", example = "200") + private Long workshopId; + + @Schema(description = "设备状态", example = "1") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java new file mode 100644 index 000000000..5e29fa881 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备台账 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvMachineryRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "设备编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "EQ-001") + @ExcelProperty("设备编码") + private String code; + + @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "CNC 加工中心") + @ExcelProperty("设备名称") + private String name; + + @Schema(description = "品牌", example = "西门子") + @ExcelProperty("品牌") + private String brand; + + @Schema(description = "规格型号", example = "S7-300") + @ExcelProperty("规格型号") + private String spec; + + @Schema(description = "设备类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long machineryTypeId; + + @Schema(description = "设备类型名称", example = "数控机床") + @ExcelProperty("设备类型") + private String machineryTypeName; + + @Schema(description = "所属车间编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + private Long workshopId; + + @Schema(description = "所属车间名称", example = "一号车间") + @ExcelProperty("所属车间") + private String workshopName; + + @Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "设备状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_MACHINERY_STATUS) + private Integer status; + + @Schema(description = "最近保养时间") + @ExcelProperty("最近保养时间") + private LocalDateTime lastMaintenTime; + + @Schema(description = "最近点检时间") + @ExcelProperty("最近点检时间") + private LocalDateTime lastCheckTime; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java new file mode 100644 index 000000000..9ff0c5d84 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备台账新增/修改 Request VO") +@Data +public class MesDvMachinerySaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "设备编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "EQ-001") + @NotEmpty(message = "设备编码不能为空") + private String code; + + @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "CNC 加工中心") + @NotEmpty(message = "设备名称不能为空") + private String name; + + @Schema(description = "品牌", example = "西门子") + private String brand; + + @Schema(description = "规格型号", example = "S7-300") + private String spec; + + @Schema(description = "设备类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "设备类型不能为空") + private Long machineryTypeId; + + @Schema(description = "所属车间编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + @NotNull(message = "所属车间不能为空") + private Long workshopId; + + @Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "设备状态不能为空") + private Integer status; + + @Schema(description = "最近保养时间") + private LocalDateTime lastMaintenTime; + + @Schema(description = "最近点检时间") + private LocalDateTime lastCheckTime; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeListReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeListReqVO.java new file mode 100644 index 000000000..47c530dfd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeListReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +@Schema(description = "管理后台 - MES 设备类型列表 Request VO") +@Data +@Accessors(chain = true) +public class MesDvMachineryTypeListReqVO { + + @Schema(description = "类型名称", example = "数控机床") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java new file mode 100644 index 000000000..80859d859 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备类型 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvMachineryTypeRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "MT-001") + @ExcelProperty("类型编码") + private String code; + + @Schema(description = "类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "数控机床") + @ExcelProperty("类型名称") + private String name; + + @Schema(description = "父类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Long parentId; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "显示排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("显示排序") + private Integer sort; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeSaveReqVO.java new file mode 100644 index 000000000..1a0f1edf3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeSaveReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 设备类型新增/修改 Request VO") +@Data +public class MesDvMachineryTypeSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "MT-001") + @NotEmpty(message = "类型编码不能为空") + private String code; + + @Schema(description = "类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "数控机床") + @NotEmpty(message = "类型名称不能为空") + private String name; + + @Schema(description = "父类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "父类型编号不能为空") + private Long parentId; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "显示排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "显示排序不能为空") + private Integer sort; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java new file mode 100644 index 000000000..5a9400c87 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java @@ -0,0 +1,155 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.dv.maintenrecord.vo.MesDvMaintenRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordDO; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import cn.iocoder.yudao.module.mes.service.dv.maintenrecord.MesDvMaintenRecordService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 设备保养记录") +@RestController +@RequestMapping("/mes/dv/mainten-record") +@Validated +public class MesDvMaintenRecordController { + + @Resource + private MesDvMaintenRecordService maintenRecordService; + + @Resource + private MesDvCheckPlanService checkPlanService; + + @Resource + private MesDvMachineryService machineryService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建设备保养记录") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:create')") + public CommonResult createMaintenRecord(@Valid @RequestBody MesDvMaintenRecordSaveReqVO createReqVO) { + return success(maintenRecordService.createMaintenRecord(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新设备保养记录") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:update')") + public CommonResult updateMaintenRecord(@Valid @RequestBody MesDvMaintenRecordSaveReqVO updateReqVO) { + maintenRecordService.updateMaintenRecord(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除设备保养记录") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:delete')") + public CommonResult deleteMaintenRecord(@RequestParam("id") Long id) { + maintenRecordService.deleteMaintenRecord(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得设备保养记录") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:query')") + public CommonResult getMaintenRecord(@RequestParam("id") Long id) { + MesDvMaintenRecordDO maintenRecord = maintenRecordService.getMaintenRecord(id); + if (maintenRecord == null) { + return success(null); + } + return success(buildMaintenRecordRespVOList(Collections.singletonList(maintenRecord)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得设备保养记录分页") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:query')") + public CommonResult> getMaintenRecordPage(@Valid MesDvMaintenRecordPageReqVO pageReqVO) { + PageResult pageResult = maintenRecordService.getMaintenRecordPage(pageReqVO); + return success(new PageResult<>(buildMaintenRecordRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出设备保养记录 Excel") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportMaintenRecordExcel(@Valid MesDvMaintenRecordPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = maintenRecordService.getMaintenRecordPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "设备保养记录.xls", "数据", MesDvMaintenRecordRespVO.class, + buildMaintenRecordRespVOList(list)); + } + + @PutMapping("/submit") + @Operation(summary = "提交设备保养记录(草稿→已提交)") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:update')") + public CommonResult submitMaintenRecord(@RequestParam("id") Long id) { + maintenRecordService.submitMaintenRecord(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildMaintenRecordRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map planMap = checkPlanService.getCheckPlanMap( + convertSet(list, MesDvMaintenRecordDO::getPlanId)); + Map machineryMap = machineryService.getMachineryMap( + convertSet(list, MesDvMaintenRecordDO::getMachineryId)); + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesDvMaintenRecordDO::getUserId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesDvMaintenRecordRespVO.class, vo -> { + MapUtils.findAndThen(planMap, vo.getPlanId(), + plan -> vo.setPlanName(plan.getName()) + .setPlanCode(plan.getCode()) + .setPlanStartDate(plan.getStartDate()) + .setPlanEndDate(plan.getEndDate()) + .setPlanCycleType(plan.getCycleType()) + .setPlanCycleCount(plan.getCycleCount())); + MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo + .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName()) + .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec())); + MapUtils.findAndThen(userMap, vo.getUserId(), + user -> vo.setNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordLineController.java new file mode 100644 index 000000000..e3616cb0b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordLineController.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.dv.maintenrecord.vo.line.MesDvMaintenRecordLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import cn.iocoder.yudao.module.mes.service.dv.maintenrecord.MesDvMaintenRecordLineService; +import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 设备保养记录明细") +@RestController +@RequestMapping("/mes/dv/mainten-record-line") +@Validated +public class MesDvMaintenRecordLineController { + + @Resource + private MesDvMaintenRecordLineService maintenRecordLineService; + + @Resource + private MesDvSubjectService subjectService; + + @PostMapping("/create") + @Operation(summary = "创建设备保养记录明细") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:create')") + public CommonResult createMaintenRecordLine(@Valid @RequestBody MesDvMaintenRecordLineSaveReqVO createReqVO) { + return success(maintenRecordLineService.createMaintenRecordLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新设备保养记录明细") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:update')") + public CommonResult updateMaintenRecordLine(@Valid @RequestBody MesDvMaintenRecordLineSaveReqVO updateReqVO) { + maintenRecordLineService.updateMaintenRecordLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除设备保养记录明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:delete')") + public CommonResult deleteMaintenRecordLine(@RequestParam("id") Long id) { + maintenRecordLineService.deleteMaintenRecordLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得设备保养记录明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:query')") + public CommonResult getMaintenRecordLine(@RequestParam("id") Long id) { + MesDvMaintenRecordLineDO maintenRecordLine = maintenRecordLineService.getMaintenRecordLine(id); + if (maintenRecordLine == null) { + return success(null); + } + return success(buildMaintenRecordLineRespVOList(Collections.singletonList(maintenRecordLine)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得设备保养记录明细分页") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:query')") + public CommonResult> getMaintenRecordLinePage(@Valid MesDvMaintenRecordLinePageReqVO pageReqVO) { + PageResult pageResult = maintenRecordLineService.getMaintenRecordLinePage(pageReqVO); + return success(new PageResult<>(buildMaintenRecordLineRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出设备保养记录明细 Excel") + @PreAuthorize("@ss.hasPermission('mes:dv-mainten-record:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportMaintenRecordLineExcel(@Valid MesDvMaintenRecordLinePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = maintenRecordLineService.getMaintenRecordLinePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "设备保养记录明细.xls", "数据", MesDvMaintenRecordLineRespVO.class, + buildMaintenRecordLineRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildMaintenRecordLineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map subjectMap = subjectService.getSubjectMap( + convertSet(list, MesDvMaintenRecordLineDO::getSubjectId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesDvMaintenRecordLineRespVO.class, vo -> + MapUtils.findAndThen(subjectMap, vo.getSubjectId(), subject -> vo + .setSubjectName(subject.getName()).setSubjectContent(subject.getContent()) + .setSubjectStandard(subject.getStandard()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordPageReqVO.java new file mode 100644 index 000000000..1e75613f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 设备保养记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvMaintenRecordPageReqVO extends PageParam { + + @Schema(description = "保养计划编号", example = "1") + private Long planId; + + @Schema(description = "设备编号", example = "1") + private Long machineryId; + + @Schema(description = "保养人编号", example = "1") + private Long userId; + + @Schema(description = "保养时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] maintenTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java new file mode 100644 index 000000000..7b8d96266 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备保养记录 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvMaintenRecordRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "计划编号", example = "1") + private Long planId; + + @Schema(description = "计划名称", example = "保养计划1") + @ExcelProperty("计划名称") + private String planName; + + @Schema(description = "计划编码", example = "P001") + @ExcelProperty("计划编码") + private String planCode; + + @Schema(description = "开始时间") + @ExcelProperty("开始时间") + private LocalDateTime planStartDate; + + @Schema(description = "结束日期") + @ExcelProperty("结束日期") + private LocalDateTime planEndDate; + + @Schema(description = "频率类型", example = "1") + @ExcelProperty(value = "频率类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_CYCLE_TYPE) + private Integer planCycleType; + + @Schema(description = "频率数量", example = "5") + @ExcelProperty(value = "频率数量") + private Integer planCycleCount; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long machineryId; + + @Schema(description = "设备编码", example = "M001") + @ExcelProperty("设备编码") + private String machineryCode; + + @Schema(description = "设备名称", example = "机床A") + @ExcelProperty("设备名称") + private String machineryName; + + @Schema(description = "品牌", example = "西门子") + @ExcelProperty("品牌") + private String machineryBrand; + + @Schema(description = "规格型号", example = "X-100") + @ExcelProperty("规格型号") + private String machinerySpec; + + @Schema(description = "保养时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("保养时间") + private LocalDateTime maintenTime; + + @Schema(description = "用户编号", example = "1") + private Long userId; + + @Schema(description = "保养人名称", example = "张三") + @ExcelProperty("保养人") + private String nickname; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_MAINTEN_RECORD_STATUS) + private Integer status; + + @Schema(description = "备注", example = "测试备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordSaveReqVO.java new file mode 100644 index 000000000..2e44d4167 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备保养记录新增/修改 Request VO") +@Data +public class MesDvMaintenRecordSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024") + private Long id; + + @Schema(description = "计划编号", example = "1") + private Long planId; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "设备不能为空") + private Long machineryId; + + @Schema(description = "保养时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "保养时间不能为空") + private LocalDateTime maintenTime; + + @Schema(description = "用户编号", example = "1") + private Long userId; + + @Schema(description = "备注", example = "测试备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLinePageReqVO.java new file mode 100644 index 000000000..047fb32e4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLinePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 设备保养记录明细分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvMaintenRecordLinePageReqVO extends PageParam { + + @Schema(description = "保养记录ID", example = "1") + private Long recordId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java new file mode 100644 index 000000000..adea3c993 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备保养记录明细 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvMaintenRecordLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "保养记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long recordId; + + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long subjectId; + + @Schema(description = "项目名称", example = "检查机油") + @ExcelProperty("项目名称") + private String subjectName; + + @Schema(description = "项目内容", example = "检查机油是否充足") + @ExcelProperty("项目内容") + private String subjectContent; + + @Schema(description = "项目标准", example = "无漏油") + @ExcelProperty("标准") + private String subjectStandard; + + @Schema(description = "保养结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "保养结果", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_MAINTEN_STATUS) + private Integer status; + + @Schema(description = "异常描述", example = "发现损坏") + @ExcelProperty("异常描述") + private String result; + + @Schema(description = "备注", example = "测试备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineSaveReqVO.java new file mode 100644 index 000000000..b6913060c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +@Schema(description = "管理后台 - MES 设备保养记录明细新增/修改 Request VO") +@Data +public class MesDvMaintenRecordLineSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024") + private Long id; + + @Schema(description = "保养记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "保养记录不能为空") + private Long recordId; + + @Schema(description = "项目编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "项目不能为空") + private Long subjectId; + + @Schema(description = "保养结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "保养结果不能为空") + private Integer status; + + @Schema(description = "异常描述", example = "发现损坏") + private String result; + + @Schema(description = "备注", example = "测试备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/package-info.java new file mode 100644 index 000000000..8cdd365a1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/package-info.java @@ -0,0 +1,4 @@ +/** + * MES 设备管理(Device / Equipment Management):设备类型、设备台账、点检计划与记录、保养记录、维修工单等设备全生命周期管理 + */ +package cn.iocoder.yudao.module.mes.controller.admin.dv; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java new file mode 100644 index 000000000..7b958cef8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java @@ -0,0 +1,171 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.dv.repair.vo.MesDvRepairPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairDO; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import cn.iocoder.yudao.module.mes.service.dv.repair.MesDvRepairService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +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.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - MES 维修工单") +@RestController +@RequestMapping("/mes/dv/repair") +@Validated +public class MesDvRepairController { + + @Resource + private MesDvRepairService repairService; + + @Resource + private MesDvMachineryService machineryService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建维修工单") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:create')") + public CommonResult createRepair(@Valid @RequestBody MesDvRepairSaveReqVO createReqVO) { + return success(repairService.createRepair(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新维修工单") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')") + public CommonResult updateRepair(@Valid @RequestBody MesDvRepairSaveReqVO updateReqVO) { + repairService.updateRepair(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除维修工单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-repair:delete')") + public CommonResult deleteRepair(@RequestParam("id") Long id) { + repairService.deleteRepair(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得维修工单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:query')") + public CommonResult getRepair(@RequestParam("id") Long id) { + MesDvRepairDO repair = repairService.getRepair(id); + if (repair == null) { + return success(null); + } + return success(buildRepairRespVOList(Collections.singletonList(repair)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得维修工单分页") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:query')") + public CommonResult> getRepairPage(@Valid MesDvRepairPageReqVO pageReqVO) { + PageResult pageResult = repairService.getRepairPage(pageReqVO); + return success(new PageResult<>(buildRepairRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出维修工单 Excel") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportRepairExcel(@Valid MesDvRepairPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = repairService.getRepairPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "维修工单.xls", "数据", MesDvRepairRespVO.class, + buildRepairRespVOList(list)); + } + + // DONE @AI:submit=>confirm=>finish(然后里面有是 resultstatus 这样的字段【对齐实体?】) + + @PutMapping("/submit") + @Operation(summary = "提交维修工单(草稿→维修中)") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')") + public CommonResult submitRepair(@RequestParam("id") Long id) { + repairService.submitRepair(id, getLoginUserId()); + return success(true); + } + + @PutMapping("/confirm") + @Operation(summary = "确认维修完成(维修中→待验收)") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')") + public CommonResult confirmRepair(@Valid @RequestBody cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairConfirmReqVO confirmReqVO) { + repairService.confirmRepair(confirmReqVO); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成验收(待验收→已确认)") + @Parameters({ + @Parameter(name = "id", description = "编号", required = true), + @Parameter(name = "result", description = "验收结果", required = true) + }) + @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')") + public CommonResult finishRepair(@RequestParam("id") Long id, + @RequestParam("result") Integer result) { + repairService.finishRepair(id, result, getLoginUserId()); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildRepairRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1.1 批量获取关联数据 + Map machineryMap = machineryService.getMachineryMap( + convertSet(list, MesDvRepairDO::getMachineryId)); + // 1.2 收集所有用户 ID(维修人 + 验收人) + Map userMap = adminUserApi.getUserMap(convertSetByFlatMap(list, + repair -> Stream.of(repair.getAcceptedUserId(), repair.getConfirmUserId()))); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesDvRepairRespVO.class, vo -> { + MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo + .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName()) + .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec())); + MapUtils.findAndThen(userMap, vo.getAcceptedUserId(), + user -> vo.setAcceptedUserNickname(user.getNickname())); + MapUtils.findAndThen(userMap, vo.getConfirmUserId(), + user -> vo.setConfirmUserNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairLineController.java new file mode 100644 index 000000000..b0e6ccf84 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairLineController.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.dv.repair.vo.line.MesDvRepairLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import cn.iocoder.yudao.module.mes.service.dv.repair.MesDvRepairLineService; +import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 维修工单行") +@RestController +@RequestMapping("/mes/dv/repair-line") +@Validated +public class MesDvRepairLineController { + + @Resource + private MesDvRepairLineService repairLineService; + + @Resource + private MesDvSubjectService subjectService; + + @PostMapping("/create") + @Operation(summary = "创建维修工单行") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:create')") + public CommonResult createRepairLine(@Valid @RequestBody MesDvRepairLineSaveReqVO createReqVO) { + return success(repairLineService.createRepairLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新维修工单行") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:update')") + public CommonResult updateRepairLine(@Valid @RequestBody MesDvRepairLineSaveReqVO updateReqVO) { + repairLineService.updateRepairLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除维修工单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-repair:delete')") + public CommonResult deleteRepairLine(@RequestParam("id") Long id) { + repairLineService.deleteRepairLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得维修工单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:query')") + public CommonResult getRepairLine(@RequestParam("id") Long id) { + MesDvRepairLineDO repairLine = repairLineService.getRepairLine(id); + if (repairLine == null) { + return success(null); + } + return success(buildRepairLineRespVOList(Collections.singletonList(repairLine)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得维修工单行分页") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:query')") + public CommonResult> getRepairLinePage(@Valid MesDvRepairLinePageReqVO pageReqVO) { + PageResult pageResult = repairLineService.getRepairLinePage(pageReqVO); + return success(new PageResult<>(buildRepairLineRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出维修工单行 Excel") + @PreAuthorize("@ss.hasPermission('mes:dv-repair:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportRepairLineExcel(@Valid MesDvRepairLinePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = repairLineService.getRepairLinePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "维修工单行.xls", "数据", MesDvRepairLineRespVO.class, + buildRepairLineRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRepairLineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map subjectMap = subjectService.getSubjectMap( + convertSet(list, MesDvRepairLineDO::getSubjectId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesDvRepairLineRespVO.class, vo -> + MapUtils.findAndThen(subjectMap, vo.getSubjectId(), subject -> vo + .setSubjectName(subject.getName()).setSubjectContent(subject.getContent()) + .setSubjectStandard(subject.getStandard()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairConfirmReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairConfirmReqVO.java new file mode 100644 index 000000000..c707ef446 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairConfirmReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 维修工单确认完成 Request VO") +@Data +public class MesDvRepairConfirmReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "维修工单编号不能为空") + private Long id; + + @Schema(description = "维修完成日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "维修完成日期不能为空") + private LocalDateTime finishDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairPageReqVO.java new file mode 100644 index 000000000..9c1dc5380 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairPageReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 维修工单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvRepairPageReqVO extends PageParam { + + @Schema(description = "维修工单编码", example = "REP2024001") + private String code; + + @Schema(description = "维修工单名称", example = "注塑机维修") + private String name; + + @Schema(description = "设备编号", example = "1") + private Long machineryId; + + @Schema(description = "维修结果", example = "1") + private Integer result; + + @Schema(description = "状态", example = "10") + private Integer status; + + @Schema(description = "报修日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] requireDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java new file mode 100644 index 000000000..48338084c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 维修工单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvRepairRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "维修工单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "REP2024001") + @ExcelProperty("维修工单编码") + private String code; + + @Schema(description = "维修工单名称", example = "注塑机液压系统维修") + @ExcelProperty("维修工单名称") + private String name; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long machineryId; + + @Schema(description = "设备编码", example = "M001") + @ExcelProperty("设备编码") + private String machineryCode; + + @Schema(description = "设备名称", example = "注塑机") + @ExcelProperty("设备名称") + private String machineryName; + + @Schema(description = "品牌", example = "西门子") + @ExcelProperty("品牌") + private String machineryBrand; + + @Schema(description = "规格型号", example = "X-100") + @ExcelProperty("规格型号") + private String machinerySpec; + + @Schema(description = "报修日期") + @ExcelProperty("报修日期") + private LocalDateTime requireDate; + + @Schema(description = "维修完成日期") + @ExcelProperty("维修完成日期") + private LocalDateTime finishDate; + + @Schema(description = "验收日期") + @ExcelProperty("验收日期") + private LocalDateTime confirmDate; + + @Schema(description = "维修结果", example = "1") + @ExcelProperty(value = "维修结果", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_REPAIR_RESULT) + private Integer result; + + @Schema(description = "维修人用户编号", example = "1") + private Long acceptedUserId; + + @Schema(description = "维修人名称", example = "张三") + @ExcelProperty("维修人") + private String acceptedUserNickname; + + @Schema(description = "验收人用户编号", example = "1") + private Long confirmUserId; + + @Schema(description = "验收人名称", example = "李四") + @ExcelProperty("验收人") + private String confirmUserNickname; + + @Schema(description = "来源单据类型", example = "1") + private Integer sourceDocType; + + @Schema(description = "来源单据编号", example = "1") + private Long sourceDocId; + + @Schema(description = "来源单据编码", example = "DOC001") + private String sourceDocCode; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_REPAIR_STATUS) + private Integer status; + + @Schema(description = "备注", example = "测试备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairSaveReqVO.java new file mode 100644 index 000000000..d841153d4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairSaveReqVO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 维修工单新增/修改 Request VO") +@Data +public class MesDvRepairSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024") + private Long id; + + @Schema(description = "维修工单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "REP2024001") + @NotBlank(message = "维修工单编码不能为空") + private String code; + + @Schema(description = "维修工单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "注塑机液压系统维修") + @NotBlank(message = "维修工单名称不能为空") + private String name; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "设备不能为空") + private Long machineryId; + + @Schema(description = "报修日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "报修日期不能为空") + private LocalDateTime requireDate; + + @Schema(description = "维修完成日期") + private LocalDateTime finishDate; + + @Schema(description = "验收日期") + private LocalDateTime confirmDate; + + @Schema(description = "维修结果", example = "1") + private Integer result; + + @Schema(description = "维修人用户编号", example = "1") + private Long acceptedUserId; + + @Schema(description = "验收人用户编号", example = "1") + private Long confirmUserId; + + @Schema(description = "来源单据类型", example = "1") + private Integer sourceDocType; + + @Schema(description = "来源单据编号", example = "1") + private Long sourceDocId; + + @Schema(description = "来源单据编码", example = "DOC001") + private String sourceDocCode; + + @Schema(description = "备注", example = "测试备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLinePageReqVO.java new file mode 100644 index 000000000..759fece12 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLinePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 维修工单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvRepairLinePageReqVO extends PageParam { + + @Schema(description = "维修工单编号", example = "1") + private Long repairId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java new file mode 100644 index 000000000..3adcda5e7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 维修工单行 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvRepairLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "维修工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long repairId; + + @Schema(description = "点检保养项目编号", example = "1") + private Long subjectId; + + @Schema(description = "项目名称", example = "检查机油") + @ExcelProperty("项目名称") + private String subjectName; + + @Schema(description = "项目内容", example = "检查机油是否充足") + @ExcelProperty("项目内容") + private String subjectContent; + + @Schema(description = "项目标准", example = "无漏油") + @ExcelProperty("标准") + private String subjectStandard; + + @Schema(description = "故障描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "液压系统漏油") + @ExcelProperty("故障描述") + private String malfunction; + + @Schema(description = "故障图片 URL", example = "https://example.com/image.png") + private String malfunctionUrl; + + @Schema(description = "维修描述", example = "更换密封圈") + @ExcelProperty("维修描述") + private String description; + + @Schema(description = "备注", example = "测试备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineSaveReqVO.java new file mode 100644 index 000000000..75c73c806 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineSaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +@Schema(description = "管理后台 - MES 维修工单行新增/修改 Request VO") +@Data +public class MesDvRepairLineSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1024") + private Long id; + + @Schema(description = "维修工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "维修工单不能为空") + private Long repairId; + + @Schema(description = "点检保养项目编号", example = "1") + private Long subjectId; + + @Schema(description = "故障描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "液压系统漏油") + @NotBlank(message = "故障描述不能为空") + private String malfunction; + + @Schema(description = "故障图片 URL", example = "https://example.com/image.png") + private String malfunctionUrl; + + @Schema(description = "维修描述", example = "更换密封圈") + private String description; + + @Schema(description = "备注", example = "测试备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/MesDvSubjectController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/MesDvSubjectController.java new file mode 100644 index 000000000..c18d7f98b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/MesDvSubjectController.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.subject; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.dv.subject.vo.MesDvSubjectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 点检保养项目") +@RestController +@RequestMapping("/mes/dv/subject") +@Validated +public class MesDvSubjectController { + + @Resource + private MesDvSubjectService subjectService; + + @PostMapping("/create") + @Operation(summary = "创建点检保养项目") + @PreAuthorize("@ss.hasPermission('mes:dv-subject:create')") + public CommonResult createSubject(@Valid @RequestBody MesDvSubjectSaveReqVO createReqVO) { + return success(subjectService.createSubject(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新点检保养项目") + @PreAuthorize("@ss.hasPermission('mes:dv-subject:update')") + public CommonResult updateSubject(@Valid @RequestBody MesDvSubjectSaveReqVO updateReqVO) { + subjectService.updateSubject(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除点检保养项目") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:dv-subject:delete')") + public CommonResult deleteSubject(@RequestParam("id") Long id) { + subjectService.deleteSubject(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得点检保养项目") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:dv-subject:query')") + public CommonResult getSubject(@RequestParam("id") Long id) { + MesDvSubjectDO subject = subjectService.getSubject(id); + return success(BeanUtils.toBean(subject, MesDvSubjectRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得点检保养项目分页") + @PreAuthorize("@ss.hasPermission('mes:dv-subject:query')") + public CommonResult> getSubjectPage(@Valid MesDvSubjectPageReqVO pageReqVO) { + PageResult pageResult = subjectService.getSubjectPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesDvSubjectRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得点检保养项目精简列表", description = "主要用于前端的下拉选项") + @PreAuthorize("@ss.hasPermission('mes:dv-subject:query')") + public CommonResult> getSubjectSimpleList() { + List list = subjectService.getSubjectList(); + return success(BeanUtils.toBean(list, MesDvSubjectRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出点检保养项目 Excel") + @PreAuthorize("@ss.hasPermission('mes:dv-subject:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportSubjectExcel(@Valid MesDvSubjectPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = subjectService.getSubjectPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "点检保养项目.xls", "数据", MesDvSubjectRespVO.class, + BeanUtils.toBean(list, MesDvSubjectRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectPageReqVO.java new file mode 100644 index 000000000..73495d967 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 点检保养项目分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesDvSubjectPageReqVO extends PageParam { + + @Schema(description = "项目编码", example = "CHK001") + private String code; + + @Schema(description = "项目名称", example = "注塑机外观检查") + private String name; + + @Schema(description = "项目类型", example = "1") + private Integer type; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java new file mode 100644 index 000000000..03b04edc8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 点检保养项目 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesDvSubjectRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "项目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CHK001") + @ExcelProperty("项目编码") + private String code; + + @Schema(description = "项目名称", example = "注塑机外观检查") + @ExcelProperty("项目名称") + private String name; + + @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "项目类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DV_SUBJECT_TYPE) + private Integer type; + + @Schema(description = "项目内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "检查注塑机外壳是否有裂纹") + @ExcelProperty("项目内容") + private String content; + + @Schema(description = "标准", example = "外观完好,无明显损伤") + @ExcelProperty("标准") + private String standard; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat("common_status") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectSaveReqVO.java new file mode 100644 index 000000000..93644f51b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectSaveReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 点检保养项目新增/修改 Request VO") +@Data +public class MesDvSubjectSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "项目编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CHK001") + @NotEmpty(message = "项目编码不能为空") + private String code; + + @Schema(description = "项目名称", example = "注塑机外观检查") + private String name; + + @Schema(description = "项目类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "项目类型不能为空") + private Integer type; + + @Schema(description = "项目内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "检查注塑机外壳是否有裂纹") + @NotEmpty(message = "项目内容不能为空") + private String content; + + @Schema(description = "标准", example = "外观完好,无明显损伤") + private String standard; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/MesHomeStatisticsController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/MesHomeStatisticsController.java new file mode 100644 index 000000000..37bbdeb21 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/MesHomeStatisticsController.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.home; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeProductionTrendRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeSummaryRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeWorkOrderStatusRespVO; +import cn.iocoder.yudao.module.mes.service.home.MesHomeStatisticsService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 首页统计") +@RestController +@RequestMapping("/mes/home-statistics") +@Validated +public class MesHomeStatisticsController { + + @Resource + private MesHomeStatisticsService homeStatisticsService; + + @GetMapping("/summary") + @Operation(summary = "获得首页汇总统计") + @PreAuthorize("@ss.hasPermission('mes:home:query')") + public CommonResult getHomeSummary() { + return success(homeStatisticsService.getHomeSummary()); + } + + @GetMapping("/work-order-status") + @Operation(summary = "获得工单状态分布") + @PreAuthorize("@ss.hasPermission('mes:home:query')") + public CommonResult> getWorkOrderStatusDistribution() { + return success(homeStatisticsService.getWorkOrderStatusDistribution()); + } + + @GetMapping("/production-trend") + @Operation(summary = "获得生产趋势") + @Parameter(name = "days", description = "天数", example = "7") + @PreAuthorize("@ss.hasPermission('mes:home:query')") + public CommonResult> getProductionTrend( + @RequestParam(value = "days", defaultValue = "7") @Min(1) @Max(90) Integer days) { + return success(homeStatisticsService.getProductionTrend(days)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeProductionTrendRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeProductionTrendRespVO.java new file mode 100644 index 000000000..dec50f552 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeProductionTrendRespVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.controller.admin.home.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 首页生产趋势 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MesHomeProductionTrendRespVO { + + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-04-05") + private String date; + + @Schema(description = "产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234") + private BigDecimal quantity; + + @Schema(description = "合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1200") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不良品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "34") + private BigDecimal unqualifiedQuantity; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeSummaryRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeSummaryRespVO.java new file mode 100644 index 000000000..4a36bb14f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeSummaryRespVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.controller.admin.home.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 首页汇总统计 Response VO") +@Data +public class MesHomeSummaryRespVO { + + // ========== 工单统计 ========== + + @Schema(description = "进行中工单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "12") + private Long workOrderActiveCount; + + @Schema(description = "待排产工单数(草稿)", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + private Long workOrderPrepareCount; + + @Schema(description = "已完成工单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") + private Long workOrderFinishedCount; + + // ========== 产量统计 ========== + + @Schema(description = "今日报工总产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234") + private BigDecimal todayOutput; + + @Schema(description = "昨日报工总产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1100") + private BigDecimal yesterdayOutput; + + // ========== 质量统计 ========== + + @Schema(description = "今日合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1200") + private BigDecimal todayQualifiedQuantity; + + @Schema(description = "今日不良品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "34") + private BigDecimal todayUnqualifiedQuantity; + + // ========== 设备统计 ========== + + @Schema(description = "设备总数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + private Long machineryTotal; + + @Schema(description = "运行中设备数", requiredMode = Schema.RequiredMode.REQUIRED, example = "15") + private Long machineryProducing; + + @Schema(description = "停机设备数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") + private Long machineryStop; + + @Schema(description = "维护中设备数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long machineryMaintenance; + + // ========== 异常/待办统计 ========== + + @Schema(description = "未处置安灯报警数", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") + private Long andonActiveCount; + + @Schema(description = "未完成维修工单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long repairActiveCount; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeWorkOrderStatusRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeWorkOrderStatusRespVO.java new file mode 100644 index 000000000..e2b7307ae --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/home/vo/MesHomeWorkOrderStatusRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.mes.controller.admin.home.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Schema(description = "管理后台 - MES 首页工单状态分布 Response VO") +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MesHomeWorkOrderStatusRespVO { + + @Schema(description = "状态值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; + + @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "草稿") + private String statusName; + + @Schema(description = "工单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12") + private Long count; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java new file mode 100644 index 000000000..a38e5e2e8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodePartService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 编码规则组成") +@RestController +@RequestMapping("/mes/md/auto-code-part") +@Validated +public class MesMdAutoCodePartController { + + @Resource + private MesMdAutoCodePartService partService; + + @PostMapping("/create") + @Operation(summary = "创建规则组成") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')") + public CommonResult createAutoCodePart(@Valid @RequestBody MesMdAutoCodePartSaveReqVO createReqVO) { + return success(partService.createAutoCodePart(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新规则组成") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')") + public CommonResult updateAutoCodePart(@Valid @RequestBody MesMdAutoCodePartSaveReqVO updateReqVO) { + partService.updateAutoCodePart(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除规则组成") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')") + public CommonResult deleteAutoCodePart(@RequestParam("id") Long id) { + partService.deleteAutoCodePart(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得规则组成") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult getAutoCodePart(@RequestParam("id") Long id) { + MesMdAutoCodePartDO part = partService.getAutoCodePart(id); + return success(BeanUtils.toBean(part, MesMdAutoCodePartRespVO.class)); + } + + @GetMapping("/list-by-rule-id") + @Operation(summary = "根据规则 ID 获得规则组成列表") + @Parameter(name = "ruleId", description = "规则 ID", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult> getAutoCodePartListByRuleId(@RequestParam("ruleId") Long ruleId) { + List list = partService.getAutoCodePartListByRuleId(ruleId); + return success(BeanUtils.toBean(list, MesMdAutoCodePartRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java new file mode 100644 index 000000000..aef637c1c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.record.MesMdAutoCodeGenerateReqVO; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 编码生成记录") +@RestController +@RequestMapping("/mes/md/auto-code-record") +@Validated +public class MesMdAutoCodeRecordController { + + @Resource + private MesMdAutoCodeRecordService autoCodeRecordService; + + @PostMapping("/generate") + @Operation(summary = "生成编码") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult generateAutoCode(@Valid @RequestBody MesMdAutoCodeGenerateReqVO generateReqVO) { + String code = autoCodeRecordService.generateAutoCode(generateReqVO.getRuleCode(), generateReqVO.getInputChar()); + return success(code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java new file mode 100644 index 000000000..2194104d9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.md.autocode.vo.rule.MesMdAutoCodeRulePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRuleService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +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.convertList; + +@Tag(name = "管理后台 - MES 编码规则") +@RestController +@RequestMapping("/mes/md/auto-code-rule") +@Validated +public class MesMdAutoCodeRuleController { + + @Resource + private MesMdAutoCodeRuleService ruleService; + + @PostMapping("/create") + @Operation(summary = "创建编码规则") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:create')") + public CommonResult createAutoCodeRule(@Valid @RequestBody MesMdAutoCodeRuleSaveReqVO createReqVO) { + return success(ruleService.createAutoCodeRule(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新编码规则") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')") + public CommonResult updateAutoCodeRule(@Valid @RequestBody MesMdAutoCodeRuleSaveReqVO updateReqVO) { + ruleService.updateAutoCodeRule(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除编码规则") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:delete')") + public CommonResult deleteAutoCodeRule(@RequestParam("id") Long id) { + ruleService.deleteAutoCodeRule(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得编码规则") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult getAutoCodeRule(@RequestParam("id") Long id) { + MesMdAutoCodeRuleDO rule = ruleService.getAutoCodeRule(id); + return success(BeanUtils.toBean(rule, MesMdAutoCodeRuleRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得编码规则分页") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult> getAutoCodeRulePage(@Valid MesMdAutoCodeRulePageReqVO pageReqVO) { + PageResult pageResult = ruleService.getAutoCodeRulePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesMdAutoCodeRuleRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得编码规则精简列表", description = "只包含被开启的编码规则,主要用于前端的下拉选项") + public CommonResult> getAutoCodeRuleSimpleList() { + List list = ruleService.getAutoCodeRuleListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, rule -> new MesMdAutoCodeRuleRespVO() + .setId(rule.getId()).setName(rule.getName()).setCode(rule.getCode()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出编码规则 Excel") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportAutoCodeRuleExcel(@Valid MesMdAutoCodeRulePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = ruleService.getAutoCodeRulePage(pageReqVO).getList(); + List data = BeanUtils.toBean(list, MesMdAutoCodeRuleRespVO.class); + ExcelUtils.write(response, "编码规则.xls", "数据", MesMdAutoCodeRuleRespVO.class, data); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java new file mode 100644 index 000000000..a184bc206 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 编码规则组成 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdAutoCodePartRespVO { + + @Schema(description = "分段 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("分段 ID") + private Long id; + + @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("规则 ID") + private Long ruleId; + + @Schema(description = "分段序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("分段序号") + private Integer sort; + + @Schema(description = "分段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "分段类型", converter = DictConvert.class) + @DictFormat("mes_auto_code_part_type") + private Integer type; + + @Schema(description = "分段长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "4") + @ExcelProperty("分段长度") + private Integer length; + + @Schema(description = "日期格式", example = "yyyyMMdd") + @ExcelProperty("日期格式") + private String dateFormat; + + @Schema(description = "固定字符", example = "ITEM_") + @ExcelProperty("固定字符") + private String fixCharacter; + + @Schema(description = "流水号起始值", example = "1") + @ExcelProperty("流水号起始值") + private Integer serialStartNo; + + @Schema(description = "流水号步长", example = "1") + @ExcelProperty("流水号步长") + private Integer serialStep; + + @Schema(description = "流水号是否循环", example = "true") + @ExcelProperty("流水号是否循环") + private Boolean cycleFlag; + + @Schema(description = "循环方式", example = "3") + @ExcelProperty(value = "循环方式", converter = DictConvert.class) + @DictFormat("mes_auto_code_cycle_method") + private Integer cycleMethod; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java new file mode 100644 index 000000000..d1c6502f1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 编码规则组成新增/修改 Request VO") +@Data +public class MesMdAutoCodePartSaveReqVO { + + @Schema(description = "分段 ID", example = "1024") + private Long id; + + @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "规则 ID 不能为空") + private Long ruleId; + + @Schema(description = "分段序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "分段序号不能为空") + private Integer sort; + + @Schema(description = "分段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "分段类型不能为空") + private Integer type; + + @Schema(description = "分段长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "4") + @NotNull(message = "分段长度不能为空") + private Integer length; + + @Schema(description = "日期格式", example = "yyyyMMdd") + private String dateFormat; + + @Schema(description = "固定字符", example = "ITEM_") + private String fixCharacter; + + @Schema(description = "流水号起始值", example = "1") + private Integer serialStartNo; + + @Schema(description = "流水号步长", example = "1") + private Integer serialStep; + + @Schema(description = "流水号是否循环", example = "true") + private Boolean cycleFlag; + + @Schema(description = "循环方式", example = "3") + private Integer cycleMethod; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java new file mode 100644 index 000000000..4c808d419 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +@Schema(description = "管理后台 - MES 编码生成 Request VO") +@Data +public class MesMdAutoCodeGenerateReqVO { + + @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE") + @NotEmpty(message = "规则编码不能为空") + private String ruleCode; + + @Schema(description = "输入字符", example = "A") + private String inputChar; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java new file mode 100644 index 000000000..6c5a0a468 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 编码规则分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdAutoCodeRulePageReqVO extends PageParam { + + @Schema(description = "规则编码", example = "ITEM_CODE") + private String code; + + @Schema(description = "规则名称", example = "物料编码规则") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java new file mode 100644 index 000000000..5c69f74ff --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 编码规则 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdAutoCodeRuleRespVO { + + @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("规则 ID") + private Long id; + + @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE") + @ExcelProperty("规则编码") + private String code; + + @Schema(description = "规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料编码规则") + @ExcelProperty("规则名称") + private String name; + + @Schema(description = "描述", example = "用于生成物料编码") + @ExcelProperty("描述") + private String description; + + @Schema(description = "最大长度", example = "20") + @ExcelProperty("最大长度") + private Integer maxLength; + + @Schema(description = "是否补齐", example = "true") + @ExcelProperty("是否补齐") + private Boolean padded; + + @Schema(description = "补齐字符", example = "0") + @ExcelProperty("补齐字符") + private String paddedChar; + + @Schema(description = "补齐方式", example = "1") + @ExcelProperty(value = "补齐方式", converter = DictConvert.class) + @DictFormat("mes_auto_code_padded_method") + private Integer paddedMethod; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java new file mode 100644 index 000000000..fd9b76912 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 编码规则新增/修改 Request VO") +@Data +public class MesMdAutoCodeRuleSaveReqVO { + + @Schema(description = "规则 ID", example = "1024") + private Long id; + + @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE") + @NotEmpty(message = "规则编码不能为空") + private String code; + + @Schema(description = "规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料编码规则") + @NotEmpty(message = "规则名称不能为空") + private String name; + + @Schema(description = "描述", example = "用于生成物料编码") + private String description; + + @Schema(description = "最大长度", example = "20") + private Integer maxLength; + + @Schema(description = "是否补齐", example = "true") + private Boolean padded; + + @Schema(description = "补齐字符", example = "0") + private String paddedChar; + + @Schema(description = "补齐方式", example = "1") + private Integer paddedMethod; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java new file mode 100644 index 000000000..95fd5c528 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/MesMdClientController.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.client; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.md.client.vo.MesMdClientImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + + +@Tag(name = "管理后台 - MES 客户") +@RestController +@RequestMapping("/mes/md-client") +@Validated +public class MesMdClientController { + + @Resource + private MesMdClientService clientService; + + @PostMapping("/create") + @Operation(summary = "创建客户") + @PreAuthorize("@ss.hasPermission('mes:md-client:create')") + public CommonResult createClient(@Valid @RequestBody MesMdClientSaveReqVO createReqVO) { + return success(clientService.createClient(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新客户") + @PreAuthorize("@ss.hasPermission('mes:md-client:update')") + public CommonResult updateClient(@Valid @RequestBody MesMdClientSaveReqVO updateReqVO) { + clientService.updateClient(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除客户") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-client:delete')") + public CommonResult deleteClient(@RequestParam("id") Long id) { + clientService.deleteClient(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得客户") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-client:query')") + public CommonResult getClient(@RequestParam("id") Long id) { + MesMdClientDO client = clientService.getClient(id); + return success(BeanUtils.toBean(client, MesMdClientRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得客户分页") + @PreAuthorize("@ss.hasPermission('mes:md-client:query')") + public CommonResult> getClientPage(@Valid MesMdClientPageReqVO pageReqVO) { + PageResult pageResult = clientService.getClientPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesMdClientRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出客户 Excel") + @PreAuthorize("@ss.hasPermission('mes:md-client:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportClientExcel(@Valid MesMdClientPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = clientService.getClientPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "客户.xls", "数据", MesMdClientRespVO.class, + BeanUtils.toBean(list, MesMdClientRespVO.class)); + } + + @GetMapping("/get-import-template") + @Operation(summary = "获得客户导入模板") + public void importTemplate(HttpServletResponse response) throws IOException { + // 手动创建导出 demo + List list = Collections.singletonList( + MesMdClientImportExcelVO.builder().code("C001").name("示例客户").nickname("示例") + .type(1).telephone("13800138000").status(0).build() + ); + // 输出 + ExcelUtils.write(response, "客户导入模板.xls", "客户列表", MesMdClientImportExcelVO.class, list); + } + + @PostMapping("/import") + @Operation(summary = "导入客户") + @Parameters({ + @Parameter(name = "file", description = "Excel 文件", required = true), + @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") + }) + @PreAuthorize("@ss.hasPermission('mes:md-client:import')") + public CommonResult importExcel(@RequestParam("file") MultipartFile file, + @RequestParam(value = "updateSupport", required = false, + defaultValue = "false") Boolean updateSupport) throws Exception { + List list = ExcelUtils.read(file, MesMdClientImportExcelVO.class); + return success(clientService.importClientList(list, updateSupport)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java new file mode 100644 index 000000000..64f5c1251 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 客户 Excel 导入 VO + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MesMdClientImportExcelVO { + + @ExcelProperty("客户编码") + private String code; + + @ExcelProperty("客户名称") + private String name; + + @ExcelProperty("客户简称") + private String nickname; + + @ExcelProperty(value = "客户类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_CLIENT_TYPE) + private Integer type; + + @ExcelProperty("客户电话") + private String telephone; + + @ExcelProperty("客户邮箱地址") + private String email; + + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS) + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java new file mode 100644 index 000000000..7554dd0ad --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Schema(description = "管理后台 - MES 客户导入 Response VO") +@Data +@Builder +public class MesMdClientImportRespVO { + + @Schema(description = "创建成功的客户编码数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List createCodes; + + @Schema(description = "更新成功的客户编码数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List updateCodes; + + @Schema(description = "导入失败的客户集合,key 为客户编码,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) + private Map failureCodes; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java new file mode 100644 index 000000000..a9c0e52b2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 客户分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdClientPageReqVO extends PageParam { + + @Schema(description = "客户编码", example = "C00184") + private String code; + + @Schema(description = "客户名称", example = "比亚迪") + private String name; + + @Schema(description = "客户简称", example = "比亚迪") + private String nickname; + + @Schema(description = "客户英文名称", example = "BYD") + private String englishName; + + @Schema(description = "客户类型", example = "1") + private Integer type; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java new file mode 100644 index 000000000..9ed58bb5b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 客户 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdClientRespVO { + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("客户编号") + private Long id; + + @Schema(description = "客户编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00184") + @ExcelProperty("客户编码") + private String code; + + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "比亚迪") + @ExcelProperty("客户名称") + private String name; + + @Schema(description = "客户简称", example = "比亚迪") + @ExcelProperty("客户简称") + private String nickname; + + @Schema(description = "客户英文名称", example = "BYD") + @ExcelProperty("客户英文名称") + private String englishName; + + @Schema(description = "客户简介", example = "比亚迪品牌诞生于深圳") + @ExcelProperty("客户简介") + private String description; + + @Schema(description = "客户LOGO地址", example = "https://xxx.com/logo.png") + private String logo; + + @Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "客户类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_CLIENT_TYPE) + private Integer type; + + @Schema(description = "客户地址", example = "深圳南山区") + @ExcelProperty("客户地址") + private String address; + + @Schema(description = "客户官网地址", example = "https://www.bydglobal.com") + @ExcelProperty("客户官网地址") + private String website; + + @Schema(description = "客户邮箱地址", example = "salse@bydglobal.com") + @ExcelProperty("客户邮箱地址") + private String email; + + @Schema(description = "客户电话", example = "123432222") + @ExcelProperty("客户电话") + private String telephone; + + @Schema(description = "联系人1", example = "张三") + @ExcelProperty("联系人1") + private String contact1Name; + + @Schema(description = "联系人1-电话", example = "122212312") + @ExcelProperty("联系人1-电话") + private String contact1Telephone; + + @Schema(description = "联系人1-邮箱", example = "s1@bydglobal.com") + @ExcelProperty("联系人1-邮箱") + private String contact1Email; + + @Schema(description = "联系人2", example = "李四") + @ExcelProperty("联系人2") + private String contact2Name; + + @Schema(description = "联系人2-电话", example = "1132323232") + @ExcelProperty("联系人2-电话") + private String contact2Telephone; + + @Schema(description = "联系人2-邮箱", example = "s2@bydglobal.com") + @ExcelProperty("联系人2-邮箱") + private String contact2Email; + + @Schema(description = "统一社会信用代码", example = "11212121") + @ExcelProperty("统一社会信用代码") + private String creditCode; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java new file mode 100644 index 000000000..1e751837e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 客户新增/修改 Request VO") +@Data +public class MesMdClientSaveReqVO { + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "客户编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00184") + @NotEmpty(message = "客户编码不能为空") + private String code; + + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "比亚迪") + @NotEmpty(message = "客户名称不能为空") + private String name; + + @Schema(description = "客户简称", example = "比亚迪") + private String nickname; + + @Schema(description = "客户英文名称", example = "BYD") + private String englishName; + + @Schema(description = "客户简介", example = "比亚迪品牌诞生于深圳") + private String description; + + @Schema(description = "客户LOGO地址", example = "https://xxx.com/logo.png") + private String logo; + + @Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "客户类型不能为空") + private Integer type; + + @Schema(description = "客户地址", example = "深圳南山区") + private String address; + + @Schema(description = "客户官网地址", example = "https://www.bydglobal.com") + private String website; + + @Schema(description = "客户邮箱地址", example = "salse@bydglobal.com") + private String email; + + @Schema(description = "客户电话", example = "123432222") + private String telephone; + + @Schema(description = "联系人1", example = "张三") + private String contact1Name; + + @Schema(description = "联系人1-电话", example = "122212312") + private String contact1Telephone; + + @Schema(description = "联系人1-邮箱", example = "s1@bydglobal.com") + private String contact1Email; + + @Schema(description = "联系人2", example = "李四") + private String contact2Name; + + @Schema(description = "联系人2-电话", example = "1132323232") + private String contact2Telephone; + + @Schema(description = "联系人2-邮箱", example = "s2@bydglobal.com") + private String contact2Email; + + @Schema(description = "统一社会信用代码", example = "11212121") + private String creditCode; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemBatchConfigController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemBatchConfigController.java new file mode 100644 index 000000000..2e8586b96 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemBatchConfigController.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.batchconfig.MesMdItemBatchConfigRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.batchconfig.MesMdItemBatchConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemBatchConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 物料批次属性配置") +@RestController +@RequestMapping("/mes/md/item-batch-config") +@Validated +public class MesMdItemBatchConfigController { + + @Resource + private MesMdItemBatchConfigService itemBatchConfigService; + + @GetMapping("/get-by-item-id") + @Operation(summary = "根据物料编号获取批次属性配置") + @Parameter(name = "itemId", description = "物料编号", required = true, example = "69") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult getItemBatchConfigByItemId( + @RequestParam("itemId") Long itemId) { + MesMdItemBatchConfigDO config = itemBatchConfigService.getItemBatchConfigByItemId(itemId); + return success(BeanUtils.toBean(config, MesMdItemBatchConfigRespVO.class)); + } + + @PostMapping("/save") + @Operation(summary = "保存批次属性配置(新增或更新)") + @PreAuthorize("@ss.hasPermission('mes:md-item:update')") + public CommonResult saveItemBatchConfig(@Valid @RequestBody MesMdItemBatchConfigSaveReqVO saveReqVO) { + return success(itemBatchConfigService.saveItemBatchConfig(saveReqVO)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java new file mode 100644 index 000000000..3a6b3780d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java @@ -0,0 +1,179 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.md.item.vo.MesMdItemImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 物料产品") +@RestController +@RequestMapping("/mes/md/item") +@Validated +public class MesMdItemController { + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdItemTypeService itemTypeService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建物料产品") + @PreAuthorize("@ss.hasPermission('mes:md-item:create')") + public CommonResult createItem(@Valid @RequestBody MesMdItemSaveReqVO createReqVO) { + return success(itemService.createItem(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新物料产品") + @PreAuthorize("@ss.hasPermission('mes:md-item:update')") + public CommonResult updateItem(@Valid @RequestBody MesMdItemSaveReqVO updateReqVO) { + itemService.updateItem(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新物料产品状态") + @Parameters({ + @Parameter(name = "id", description = "编号", required = true), + @Parameter(name = "status", description = "状态", required = true) + }) + @PreAuthorize("@ss.hasPermission('mes:md-item:update')") + public CommonResult updateItemStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + itemService.updateItemStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除物料产品") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-item:delete')") + public CommonResult deleteItem(@RequestParam("id") Long id) { + itemService.deleteItem(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得物料产品") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult getItem(@RequestParam("id") Long id) { + MesMdItemDO item = itemService.getItem(id); + return success(buildItemVO(item)); + } + + @GetMapping("/page") + @Operation(summary = "获得物料产品分页") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult> getItemPage(@Valid MesMdItemPageReqVO pageReqVO) { + PageResult pageResult = itemService.getItemPage(pageReqVO); + return success(new PageResult<>(buildItemVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出物料产品 Excel") + @PreAuthorize("@ss.hasPermission('mes:md-item:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportItemExcel(@Valid MesMdItemPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = itemService.getItemPage(pageReqVO); + // 导出 Excel + ExcelUtils.write(response, "物料产品.xls", "数据", MesMdItemRespVO.class, + buildItemVOList(pageResult.getList())); + } + + @GetMapping("/get-import-template") + @Operation(summary = "获得物料导入模板") + public void importTemplate(HttpServletResponse response) throws IOException { + // 手动创建导出 demo + List list = Collections.singletonList( + MesMdItemImportExcelVO.builder().code("ITEM001").name("螺丝").specification("M6*20") + .unitMeasureCode("PCS").itemTypeId(1L).status(0).build() + ); + // 输出 + ExcelUtils.write(response, "物料导入模板.xls", "物料列表", MesMdItemImportExcelVO.class, list); + } + + @PostMapping("/import") + @Operation(summary = "导入物料") + @Parameters({ + @Parameter(name = "file", description = "Excel 文件", required = true), + @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") + }) + @PreAuthorize("@ss.hasPermission('mes:md-item:import')") + public CommonResult importExcel(@RequestParam("file") MultipartFile file, + @RequestParam(value = "updateSupport", required = false, + defaultValue = "false") Boolean updateSupport) throws Exception { + List list = ExcelUtils.read(file, MesMdItemImportExcelVO.class); + return success(itemService.importItemList(list, updateSupport)); + } + + // ==================== 拼接 VO ==================== + + private List buildItemVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + Map itemTypeMap = itemTypeService.getItemTypeMap( + convertSet(list, MesMdItemDO::getItemTypeId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(list, MesMdItemDO::getUnitMeasureId)); + return BeanUtils.toBean(list, MesMdItemRespVO.class, item -> { + MapUtils.findAndThen(itemTypeMap, item.getItemTypeId(), + itemType -> { + item.setItemTypeName(itemType.getName()); + item.setItemOrProduct(itemType.getItemOrProduct()); + }); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> item.setUnitMeasureName(unitMeasure.getName())); + }); + } + + private MesMdItemRespVO buildItemVO(MesMdItemDO item) { + if (item == null) { + return null; + } + return CollUtil.getFirst(buildItemVOList(Collections.singletonList(item))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemTypeController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemTypeController.java new file mode 100644 index 000000000..3e0a69d8a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemTypeController.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - MES 物料产品分类") +@RestController +@RequestMapping("/mes/md/item-type") +@Validated +public class MesMdItemTypeController { + + @Resource + private MesMdItemTypeService itemTypeService; + + @PostMapping("/create") + @Operation(summary = "创建物料产品分类") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:create')") + public CommonResult createItemType(@Valid @RequestBody MesMdItemTypeSaveReqVO createReqVO) { + return success(itemTypeService.createItemType(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新物料产品分类") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:update')") + public CommonResult updateItemType(@Valid @RequestBody MesMdItemTypeSaveReqVO updateReqVO) { + itemTypeService.updateItemType(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除物料产品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-item-type:delete')") + public CommonResult deleteItemType(@RequestParam("id") Long id) { + itemTypeService.deleteItemType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得物料产品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:query')") + public CommonResult getItemType(@RequestParam("id") Long id) { + MesMdItemTypeDO itemType = itemTypeService.getItemType(id); + return success(BeanUtils.toBean(itemType, MesMdItemTypeRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得物料产品分类列表") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:query')") + public CommonResult> getItemTypeList(@Valid MesMdItemTypeListReqVO listReqVO) { + List list = itemTypeService.getItemTypeList(listReqVO); + return success(BeanUtils.toBean(list, MesMdItemTypeRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得物料产品分类精简列表", description = "只包含被开启的分类,主要用于前端的下拉选项") + public CommonResult> getItemTypeSimpleList() { + List list = itemTypeService.getItemTypeList( + new MesMdItemTypeListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + return success(convertList(list, itemType -> new MesMdItemTypeRespVO() + .setId(itemType.getId()).setName(itemType.getName()).setParentId(itemType.getParentId()) + .setCode(itemType.getCode()).setRemark(itemType.getRemark()) + .setItemOrProduct(itemType.getItemOrProduct()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductBomController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductBomController.java new file mode 100644 index 000000000..3b4c445a3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductBomController.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductBomService; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 产品BOM") +@RestController +@RequestMapping("/mes/md/product-bom") +@Validated +public class MesMdProductBomController { + + @Resource + private MesMdProductBomService productBomService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdItemTypeService itemTypeService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建产品BOM") + @PreAuthorize("@ss.hasPermission('mes:md-item:create')") + public CommonResult createProductBom(@Valid @RequestBody MesMdProductBomSaveReqVO createReqVO) { + return success(productBomService.createProductBom(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品BOM") + @PreAuthorize("@ss.hasPermission('mes:md-item:update')") + public CommonResult updateProductBom(@Valid @RequestBody MesMdProductBomSaveReqVO updateReqVO) { + productBomService.updateProductBom(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品BOM") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-item:delete')") + public CommonResult deleteProductBom(@RequestParam("id") Long id) { + productBomService.deleteProductBom(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品BOM") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult getProductBom(@RequestParam("id") Long id) { + MesMdProductBomDO productBom = productBomService.getProductBom(id); + return success(BeanUtils.toBean(productBom, MesMdProductBomRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品BOM分页") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult> getProductBomPage(@Valid MesMdProductBomPageReqVO pageReqVO) { + PageResult pageResult = productBomService.getProductBomPage(pageReqVO); + List voList = buildProductBomRespVOList(pageResult.getList()); + return success(new PageResult<>(voList, pageResult.getTotal())); + } + + @GetMapping("/list-by-item-id") + @Operation(summary = "根据物料产品编号获得产品BOM列表") + @Parameter(name = "itemId", description = "物料产品编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult> getProductBomListByItemId( + @RequestParam("itemId") Long itemId) { + List list = productBomService.getProductBomListByItemId(itemId); + return success(buildProductBomRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildProductBomRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1.1 批量获取 BOM 物料信息 + Map itemMap = itemService.getItemMap( + convertSet(list, MesMdProductBomDO::getBomItemId)); + // 1.2 批量获取计量单位信息 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 1.3 批量获取物料分类信息(用于 itemOrProduct) + Map itemTypeMap = itemTypeService.getItemTypeMap( + convertSet(itemMap.values(), MesMdItemDO::getItemTypeId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesMdProductBomRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getBomItemId(), item -> { + vo.setBomItemCode(item.getCode()); + vo.setBomItemName(item.getName()); + vo.setBomItemSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + MapUtils.findAndThen(itemTypeMap, item.getItemTypeId(), + itemType -> vo.setItemOrProduct(itemType.getItemOrProduct())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductSipController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductSipController.java new file mode 100644 index 000000000..f8b764cf5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductSipController.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip.MesMdProductSipPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip.MesMdProductSipRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip.MesMdProductSipSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductSipDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductSipService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 产品SIP") +@RestController +@RequestMapping("/mes/md/product-sip") +@Validated +public class MesMdProductSipController { + + @Resource + private MesMdProductSipService productSipService; + + @PostMapping("/create") + @Operation(summary = "创建产品SIP") + @PreAuthorize("@ss.hasPermission('mes:md-item:create')") + public CommonResult createProductSip(@Valid @RequestBody MesMdProductSipSaveReqVO createReqVO) { + return success(productSipService.createProductSip(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品SIP") + @PreAuthorize("@ss.hasPermission('mes:md-item:update')") + public CommonResult updateProductSip(@Valid @RequestBody MesMdProductSipSaveReqVO updateReqVO) { + productSipService.updateProductSip(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品SIP") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-item:delete')") + public CommonResult deleteProductSip(@RequestParam("id") Long id) { + productSipService.deleteProductSip(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品SIP") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult getProductSip(@RequestParam("id") Long id) { + MesMdProductSipDO sip = productSipService.getProductSip(id); + return success(BeanUtils.toBean(sip, MesMdProductSipRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品SIP分页") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult> getProductSipPage(@Valid MesMdProductSipPageReqVO pageReqVO) { + PageResult pageResult = productSipService.getProductSipPage(pageReqVO); + // TODO @芋艿:工序模块实现后,补充 processCode/processName 的 JOIN 逻辑 + return success(BeanUtils.toBean(pageResult, MesMdProductSipRespVO.class)); + } + + @GetMapping("/list-by-item-id") + @Operation(summary = "根据物料产品编号,获得产品SIP列表") + @Parameter(name = "itemId", description = "物料产品编号", required = true, example = "69") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult> getProductSipListByItemId( + @RequestParam("itemId") Long itemId) { + List list = productSipService.getProductSipListByItemId(itemId); + // TODO @芋艿:工序模块实现后,补充 processCode/processName 的 JOIN 逻辑 + return success(BeanUtils.toBean(list, MesMdProductSipRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductSopController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductSopController.java new file mode 100644 index 000000000..10dd96b37 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdProductSopController.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop.MesMdProductSopPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop.MesMdProductSopRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop.MesMdProductSopSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductSopDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductSopService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 产品SOP") +@RestController +@RequestMapping("/mes/md/product-sop") +@Validated +public class MesMdProductSopController { + + @Resource + private MesMdProductSopService productSopService; + + @PostMapping("/create") + @Operation(summary = "创建产品SOP") + @PreAuthorize("@ss.hasPermission('mes:md-item:create')") + public CommonResult createProductSop(@Valid @RequestBody MesMdProductSopSaveReqVO createReqVO) { + return success(productSopService.createProductSop(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品SOP") + @PreAuthorize("@ss.hasPermission('mes:md-item:update')") + public CommonResult updateProductSop(@Valid @RequestBody MesMdProductSopSaveReqVO updateReqVO) { + productSopService.updateProductSop(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品SOP") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-item:delete')") + public CommonResult deleteProductSop(@RequestParam("id") Long id) { + productSopService.deleteProductSop(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品SOP") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult getProductSop(@RequestParam("id") Long id) { + MesMdProductSopDO sop = productSopService.getProductSop(id); + return success(BeanUtils.toBean(sop, MesMdProductSopRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品SOP分页") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult> getProductSopPage(@Valid MesMdProductSopPageReqVO pageReqVO) { + PageResult pageResult = productSopService.getProductSopPage(pageReqVO); + // TODO @芋艿:工序模块实现后,补充 processCode/processName 的 JOIN 逻辑 + return success(BeanUtils.toBean(pageResult, MesMdProductSopRespVO.class)); + } + + @GetMapping("/list-by-item-id") + @Operation(summary = "根据物料产品编号,获得产品SOP列表") + @Parameter(name = "itemId", description = "物料产品编号", required = true, example = "69") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult> getProductSopListByItemId( + @RequestParam("itemId") Long itemId) { + List list = productSopService.getProductSopListByItemId(itemId); + // TODO @芋艿:工序模块实现后,补充 processCode/processName 的 JOIN 逻辑 + return success(BeanUtils.toBean(list, MesMdProductSopRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportExcelVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportExcelVO.java new file mode 100644 index 000000000..dee51f76a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportExcelVO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * 物料产品 Excel 导入 VO + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MesMdItemImportExcelVO { + + @ExcelProperty("物料编码") + private String code; + + @ExcelProperty("物料名称") + private String name; + + @ExcelProperty("规格型号") + private String specification; + + @ExcelProperty("单位编码") + private String unitMeasureCode; + + @ExcelProperty("物料分类编号") + private Long itemTypeId; + + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @ExcelProperty("是否启用安全库存") + private Boolean safeStockFlag; + + @ExcelProperty("最低库存量") + private BigDecimal minStock; + + @ExcelProperty("最高库存量") + private BigDecimal maxStock; + + @ExcelProperty("是否高值物料") + private Boolean highValue; + + @ExcelProperty("是否启用批次管理") + private Boolean batchFlag; + + @ExcelProperty("备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportRespVO.java new file mode 100644 index 000000000..de3f51bae --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Schema(description = "管理后台 - MES 物料产品导入 Response VO") +@Data +@Builder +public class MesMdItemImportRespVO { + + @Schema(description = "创建成功的物料编码数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List createCodes; + + @Schema(description = "更新成功的物料编码数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List updateCodes; + + @Schema(description = "导入失败的物料集合,key 为物料编码,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) + private Map failureCodes; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemPageReqVO.java new file mode 100644 index 000000000..ab0a5a6fa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 物料产品分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdItemPageReqVO extends PageParam { + + @Schema(description = "物料编码", example = "ITEM001") + private String code; + + @Schema(description = "物料名称", example = "螺丝") + private String name; + + @Schema(description = "物料分类编号", example = "1") + private Long itemTypeId; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java new file mode 100644 index 000000000..9ce6d9580 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 物料产品 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdItemRespVO { + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("物料编号") + private Long id; + + @Schema(description = "物料编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM001") + @ExcelProperty("物料编码") + private String code; + + @Schema(description = "物料名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "螺丝") + @ExcelProperty("物料名称") + private String name; + + @Schema(description = "规格型号", example = "M6*20") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "计量单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "202") + private Long unitMeasureId; + @Schema(description = "计量单位名称", example = "个") + @ExcelProperty("计量单位") + private String unitMeasureName; + + @Schema(description = "物料分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemTypeId; + @Schema(description = "物料分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") + @ExcelProperty("物料分类") + private String itemTypeName; + + @Schema(description = "物料/产品标识", example = "ITEM") + @ExcelProperty("物料/产品标识") + private String itemOrProduct; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "是否启用安全库存", example = "false") + @ExcelProperty("是否启用安全库存") + private Boolean safeStockFlag; + + @Schema(description = "最低库存量", example = "100.0000") + @ExcelProperty("最低库存量") + private BigDecimal minStock; + + @Schema(description = "最高库存量", example = "10000.0000") + @ExcelProperty("最高库存量") + private BigDecimal maxStock; + + @Schema(description = "是否高值物料", example = "false") + @ExcelProperty("是否高值物料") + private Boolean highValue; + + @Schema(description = "是否启用批次管理", example = "true") + @ExcelProperty("是否启用批次管理") + private Boolean batchFlag; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemSaveReqVO.java new file mode 100644 index 000000000..975f689b3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemSaveReqVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 物料产品新增/修改 Request VO") +@Data +public class MesMdItemSaveReqVO { + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "物料编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM001") + @NotEmpty(message = "物料编码不能为空") + private String code; + + @Schema(description = "物料名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "螺丝") + @NotEmpty(message = "物料名称不能为空") + private String name; + + @Schema(description = "规格型号", example = "M6*20") + private String specification; + + @Schema(description = "计量单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "202") + @NotNull(message = "计量单位不能为空") + private Long unitMeasureId; + + @Schema(description = "物料分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料分类编号不能为空") + private Long itemTypeId; + + @Schema(description = "是否启用安全库存", example = "false") + private Boolean safeStockFlag; + + @Schema(description = "最低库存量", example = "100.0000") + private BigDecimal minStock; + + @Schema(description = "最高库存量", example = "10000.0000") + private BigDecimal maxStock; + + @Schema(description = "是否高值物料", example = "false") + private Boolean highValue; + + @Schema(description = "是否启用批次管理", example = "true") + private Boolean batchFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/batchconfig/MesMdItemBatchConfigRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/batchconfig/MesMdItemBatchConfigRespVO.java new file mode 100644 index 000000000..accb2a1fb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/batchconfig/MesMdItemBatchConfigRespVO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.batchconfig; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 物料批次属性配置 Response VO") +@Data +public class MesMdItemBatchConfigRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "69") + private Long itemId; + + @Schema(description = "批次属性-生产日期", example = "true") + private Boolean produceDateFlag; + + @Schema(description = "批次属性-有效期", example = "true") + private Boolean expireDateFlag; + + @Schema(description = "批次属性-入库日期", example = "false") + private Boolean receiptDateFlag; + + @Schema(description = "批次属性-供应商", example = "false") + private Boolean vendorFlag; + + @Schema(description = "批次属性-客户", example = "false") + private Boolean clientFlag; + + @Schema(description = "批次属性-销售订单编号", example = "false") + private Boolean salesOrderCodeFlag; + + @Schema(description = "批次属性-采购订单编号", example = "false") + private Boolean purchaseOrderCodeFlag; + + @Schema(description = "批次属性-生产工单", example = "false") + private Boolean workorderFlag; + + @Schema(description = "批次属性-生产任务", example = "false") + private Boolean taskFlag; + + @Schema(description = "批次属性-工作站", example = "false") + private Boolean workstationFlag; + + @Schema(description = "批次属性-工具", example = "false") + private Boolean toolFlag; + + @Schema(description = "批次属性-模具", example = "false") + private Boolean moldFlag; + + @Schema(description = "批次属性-生产批号", example = "true") + private Boolean lotNumberFlag; + + @Schema(description = "批次属性-质量状态", example = "false") + private Boolean qualityStatusFlag; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/batchconfig/MesMdItemBatchConfigSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/batchconfig/MesMdItemBatchConfigSaveReqVO.java new file mode 100644 index 000000000..0d6130e7c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/batchconfig/MesMdItemBatchConfigSaveReqVO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.batchconfig; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 物料批次属性配置新增/修改 Request VO") +@Data +public class MesMdItemBatchConfigSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "69") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "批次属性-生产日期", example = "true") + private Boolean produceDateFlag; + + @Schema(description = "批次属性-有效期", example = "true") + private Boolean expireDateFlag; + + @Schema(description = "批次属性-入库日期", example = "false") + private Boolean receiptDateFlag; + + @Schema(description = "批次属性-供应商", example = "false") + private Boolean vendorFlag; + + @Schema(description = "批次属性-客户", example = "false") + private Boolean clientFlag; + + @Schema(description = "批次属性-销售订单编号", example = "false") + private Boolean salesOrderCodeFlag; + + @Schema(description = "批次属性-采购订单编号", example = "false") + private Boolean purchaseOrderCodeFlag; + + @Schema(description = "批次属性-生产工单", example = "false") + private Boolean workorderFlag; + + @Schema(description = "批次属性-生产任务", example = "false") + private Boolean taskFlag; + + @Schema(description = "批次属性-工作站", example = "false") + private Boolean workstationFlag; + + @Schema(description = "批次属性-工具", example = "false") + private Boolean toolFlag; + + @Schema(description = "批次属性-模具", example = "false") + private Boolean moldFlag; + + @Schema(description = "批次属性-生产批号", example = "true") + private Boolean lotNumberFlag; + + @Schema(description = "批次属性-质量状态", example = "false") + private Boolean qualityStatusFlag; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomPageReqVO.java new file mode 100644 index 000000000..cdbcc3304 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomPageReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 产品BOM分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdProductBomPageReqVO extends PageParam { + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料产品ID不能为空") + private Long itemId; + + @Schema(description = "是否启用", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomRespVO.java new file mode 100644 index 000000000..805a86c30 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 产品BOM Response VO") +@Data +public class MesMdProductBomRespVO { + + @Schema(description = "BOM编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "BOM物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Long bomItemId; + + @Schema(description = "物料使用比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.5") + private BigDecimal quantity; + + @Schema(description = "是否启用", example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + // ========== 关联展示字段 ========== + + @Schema(description = "BOM物料编码", example = "ITEM001") + private String bomItemCode; + + @Schema(description = "BOM物料名称", example = "螺丝") + private String bomItemName; + + @Schema(description = "BOM物料规格", example = "M6*20") + private String bomItemSpecification; + + @Schema(description = "计量单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "产品物料标识", example = "ITEM") + private String itemOrProduct; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomSaveReqVO.java new file mode 100644 index 000000000..426427f2c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/bom/MesMdProductBomSaveReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 产品BOM新增/修改 Request VO") +@Data +public class MesMdProductBomSaveReqVO { + + @Schema(description = "BOM编号", example = "1024") + private Long id; + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料产品ID不能为空") + private Long itemId; + + @Schema(description = "BOM物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "BOM物料ID不能为空") + private Long bomItemId; + + @Schema(description = "物料使用比例", requiredMode = Schema.RequiredMode.REQUIRED, example = "1.5") + @NotNull(message = "物料使用比例不能为空") + private BigDecimal quantity; + + @Schema(description = "是否启用", example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipPageReqVO.java new file mode 100644 index 000000000..cf78d20f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipPageReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 产品SIP分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdProductSipPageReqVO extends PageParam { + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "69") + @NotNull(message = "物料产品ID不能为空") + private Long itemId; + + @Schema(description = "标题", example = "步骤一") + private String title; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipRespVO.java new file mode 100644 index 000000000..746b3e6d8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipRespVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 产品SIP Response VO") +@Data +public class MesMdProductSipRespVO { + + @Schema(description = "SIP编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "69") + private Long itemId; + + @Schema(description = "排列顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sort; + + @Schema(description = "工序ID", example = "100") + private Long processId; + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "步骤一") + private String title; + + @Schema(description = "详细描述", example = "操作说明") + private String description; + + @Schema(description = "图片地址", example = "https://www.example.com/sip.png") + private String url; + + @Schema(description = "备注", example = "备注信息") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + @Schema(description = "工序编号", example = "PROC001") + private String processCode; + + @Schema(description = "工序名称", example = "焊接工序") + private String processName; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipSaveReqVO.java new file mode 100644 index 000000000..c8d9148ca --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sip/MesMdProductSipSaveReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 产品SIP新增/修改 Request VO") +@Data +public class MesMdProductSipSaveReqVO { + + @Schema(description = "SIP编号", example = "1024") + private Long id; + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "69") + @NotNull(message = "物料产品ID不能为空") + private Long itemId; + + @Schema(description = "排列顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "排列顺序不能为空") + private Integer sort; + + @Schema(description = "工序ID", example = "100") + private Long processId; + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "步骤一") + @NotEmpty(message = "标题不能为空") + private String title; + + @Schema(description = "详细描述", example = "操作说明") + private String description; + + @Schema(description = "图片地址", example = "https://www.example.com/sip.png") + private String url; + + @Schema(description = "备注", example = "备注信息") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopPageReqVO.java new file mode 100644 index 000000000..4a90b62aa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopPageReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 产品SOP分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdProductSopPageReqVO extends PageParam { + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "69") + @NotNull(message = "物料产品ID不能为空") + private Long itemId; + + @Schema(description = "标题", example = "步骤一") + private String title; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopRespVO.java new file mode 100644 index 000000000..1a878bc89 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopRespVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 产品SOP Response VO") +@Data +public class MesMdProductSopRespVO { + + @Schema(description = "SOP编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "69") + private Long itemId; + + @Schema(description = "排列顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sort; + + @Schema(description = "工序ID", example = "100") + private Long processId; + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "步骤一") + private String title; + + @Schema(description = "详细描述", example = "操作说明") + private String description; + + @Schema(description = "图片地址", example = "https://www.example.com/sop.png") + private String url; + + @Schema(description = "备注", example = "备注信息") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + @Schema(description = "工序编号", example = "PROC001") + private String processCode; + + @Schema(description = "工序名称", example = "焊接工序") + private String processName; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopSaveReqVO.java new file mode 100644 index 000000000..4e79076f0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/sop/MesMdProductSopSaveReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 产品SOP新增/修改 Request VO") +@Data +public class MesMdProductSopSaveReqVO { + + @Schema(description = "SOP编号", example = "1024") + private Long id; + + @Schema(description = "物料产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "69") + @NotNull(message = "物料产品ID不能为空") + private Long itemId; + + @Schema(description = "排列顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "排列顺序不能为空") + private Integer sort; + + @Schema(description = "工序ID", example = "100") + private Long processId; + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "步骤一") + @NotEmpty(message = "标题不能为空") + private String title; + + @Schema(description = "详细描述", example = "操作说明") + private String description; + + @Schema(description = "图片地址", example = "https://www.example.com/sop.png") + private String url; + + @Schema(description = "备注", example = "备注信息") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeListReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeListReqVO.java new file mode 100644 index 000000000..fde88cbab --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeListReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - MES 物料产品分类列表 Request VO") +@Data +public class MesMdItemTypeListReqVO { + + @Schema(description = "分类名称", example = "原材料") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java new file mode 100644 index 000000000..447cbe733 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 物料产品分类 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdItemTypeRespVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("分类编号") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("父分类编号") + private Long parentId; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "RAW") + @ExcelProperty("分类编码") + private String code; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") + @ExcelProperty("分类名称") + private String name; + + @Schema(description = "物料/产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM") + @ExcelProperty("物料/产品标识") + private String itemOrProduct; + + @Schema(description = "显示排序", example = "0") + @ExcelProperty("显示排序") + private Integer sort; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeSaveReqVO.java new file mode 100644 index 000000000..f00918a88 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeSaveReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 物料产品分类新增/修改 Request VO") +@Data +public class MesMdItemTypeSaveReqVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "父分类编号不能为空") + private Long parentId; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "RAW") + @NotEmpty(message = "分类编码不能为空") + private String code; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") + @NotEmpty(message = "分类名称不能为空") + private String name; + + @Schema(description = "物料/产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM") + @NotEmpty(message = "物料/产品标识不能为空") + private String itemOrProduct; + + @Schema(description = "显示排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "显示排序不能为空") + private Integer sort; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/package-info.java new file mode 100644 index 000000000..005002443 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/package-info.java @@ -0,0 +1,4 @@ +/** + * MES 基础数据(Master Data):物料、物料分类、计量单位、客户、供应商、车间、工作站、BOM、SOP、SIP 等制造基础主数据 + */ +package cn.iocoder.yudao.module.mes.controller.admin.md; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/MesMdUnitMeasureController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/MesMdUnitMeasureController.java new file mode 100644 index 000000000..b2e443b39 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/MesMdUnitMeasureController.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.md.unitmeasure.vo.MesMdUnitMeasurePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasureRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasureSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +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.convertList; + +@Tag(name = "管理后台 - MES 计量单位") +@RestController +@RequestMapping("/mes/md/unit-measure") +@Validated +public class MesMdUnitMeasureController { + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建计量单位") + @PreAuthorize("@ss.hasPermission('mes:md-unit-measure:create')") + public CommonResult createUnitMeasure(@Valid @RequestBody MesMdUnitMeasureSaveReqVO createReqVO) { + return success(unitMeasureService.createUnitMeasure(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新计量单位") + @PreAuthorize("@ss.hasPermission('mes:md-unit-measure:update')") + public CommonResult updateUnitMeasure(@Valid @RequestBody MesMdUnitMeasureSaveReqVO updateReqVO) { + unitMeasureService.updateUnitMeasure(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除计量单位") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-unit-measure:delete')") + public CommonResult deleteUnitMeasure(@RequestParam("id") Long id) { + unitMeasureService.deleteUnitMeasure(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得计量单位") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-unit-measure:query')") + public CommonResult getUnitMeasure(@RequestParam("id") Long id) { + MesMdUnitMeasureDO unitMeasure = unitMeasureService.getUnitMeasure(id); + return success(BeanUtils.toBean(unitMeasure, MesMdUnitMeasureRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得计量单位分页") + @PreAuthorize("@ss.hasPermission('mes:md-unit-measure:query')") + public CommonResult> getUnitMeasurePage(@Valid MesMdUnitMeasurePageReqVO pageReqVO) { + PageResult pageResult = unitMeasureService.getUnitMeasurePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesMdUnitMeasureRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得计量单位精简列表", description = "只包含被开启的单位,主要用于前端的下拉选项") + public CommonResult> getUnitMeasureSimpleList() { + List list = unitMeasureService.getUnitMeasureListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, unit -> new MesMdUnitMeasureRespVO() + .setId(unit.getId()).setCode(unit.getCode()).setName(unit.getName()) + .setPrimaryFlag(unit.getPrimaryFlag()).setPrimaryId(unit.getPrimaryId()) + .setChangeRate(unit.getChangeRate()).setRemark(unit.getRemark()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出计量单位 Excel") + @PreAuthorize("@ss.hasPermission('mes:md-unit-measure:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportUnitMeasureExcel(@Valid MesMdUnitMeasurePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = unitMeasureService.getUnitMeasurePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "计量单位.xls", "数据", MesMdUnitMeasureRespVO.class, + BeanUtils.toBean(list, MesMdUnitMeasureRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasurePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasurePageReqVO.java new file mode 100644 index 000000000..bf964af63 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasurePageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 计量单位分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdUnitMeasurePageReqVO extends PageParam { + + @Schema(description = "单位编码", example = "KG") + private String code; + + @Schema(description = "单位名称", example = "公斤") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureRespVO.java new file mode 100644 index 000000000..033ddb4e9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureRespVO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 计量单位 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdUnitMeasureRespVO { + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("单位编号") + private Long id; + + @Schema(description = "单位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "KG") + @ExcelProperty("单位编码") + private String code; + + @Schema(description = "单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "公斤") + @ExcelProperty("单位名称") + private String name; + + @Schema(description = "是否主单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty("是否主单位") + private Boolean primaryFlag; + + @Schema(description = "主单位编号", example = "200") + @ExcelProperty("主单位编号") + private Long primaryId; + + @Schema(description = "与主单位换算比例", example = "1000.0000") + @ExcelProperty("与主单位换算比例") + private BigDecimal changeRate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureSaveReqVO.java new file mode 100644 index 000000000..15ae7ebfe --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 计量单位新增/修改 Request VO") +@Data +public class MesMdUnitMeasureSaveReqVO { + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "单位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "KG") + @NotEmpty(message = "单位编码不能为空") + private String code; + + @Schema(description = "单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "公斤") + @NotEmpty(message = "单位名称不能为空") + private String name; + + @Schema(description = "是否主单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否主单位不能为空") + private Boolean primaryFlag; + + @Schema(description = "主单位编号", example = "200") + private Long primaryId; + + @Schema(description = "与主单位换算比例", example = "1000.0000") + private BigDecimal changeRate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + @InEnum(CommonStatusEnum.class) + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/MesMdVendorController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/MesMdVendorController.java new file mode 100644 index 000000000..c362150ee --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/MesMdVendorController.java @@ -0,0 +1,124 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.vendor; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.md.vendor.vo.MesMdVendorImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 供应商") +@RestController +@RequestMapping("/mes/md-vendor") +@Validated +public class MesMdVendorController { + + @Resource + private MesMdVendorService vendorService; + + @PostMapping("/create") + @Operation(summary = "创建供应商") + @PreAuthorize("@ss.hasPermission('mes:md-vendor:create')") + public CommonResult createVendor(@Valid @RequestBody MesMdVendorSaveReqVO createReqVO) { + return success(vendorService.createVendor(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新供应商") + @PreAuthorize("@ss.hasPermission('mes:md-vendor:update')") + public CommonResult updateVendor(@Valid @RequestBody MesMdVendorSaveReqVO updateReqVO) { + vendorService.updateVendor(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除供应商") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-vendor:delete')") + public CommonResult deleteVendor(@RequestParam("id") Long id) { + vendorService.deleteVendor(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得供应商") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-vendor:query')") + public CommonResult getVendor(@RequestParam("id") Long id) { + MesMdVendorDO vendor = vendorService.getVendor(id); + return success(BeanUtils.toBean(vendor, MesMdVendorRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得供应商分页") + @PreAuthorize("@ss.hasPermission('mes:md-vendor:query')") + public CommonResult> getVendorPage(@Valid MesMdVendorPageReqVO pageReqVO) { + PageResult pageResult = vendorService.getVendorPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesMdVendorRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出供应商 Excel") + @PreAuthorize("@ss.hasPermission('mes:md-vendor:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportVendorExcel(@Valid MesMdVendorPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = vendorService.getVendorPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "供应商.xls", "数据", MesMdVendorRespVO.class, + BeanUtils.toBean(list, MesMdVendorRespVO.class)); + } + + @GetMapping("/get-import-template") + @Operation(summary = "获得供应商导入模板") + public void importTemplate(HttpServletResponse response) throws IOException { + // 手动创建导出 demo + List list = Collections.singletonList( + MesMdVendorImportExcelVO.builder().code("V001").name("示例供应商").nickname("示例") + .level("A").telephone("13800138000").status(0).build() + ); + // 输出 + ExcelUtils.write(response, "供应商导入模板.xls", "供应商列表", MesMdVendorImportExcelVO.class, list); + } + + @PostMapping("/import") + @Operation(summary = "导入供应商") + @Parameters({ + @Parameter(name = "file", description = "Excel 文件", required = true), + @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") + }) + @PreAuthorize("@ss.hasPermission('mes:md-vendor:import')") + public CommonResult importExcel(@RequestParam("file") MultipartFile file, + @RequestParam(value = "updateSupport", required = false, + defaultValue = "false") Boolean updateSupport) throws Exception { + List list = ExcelUtils.read(file, MesMdVendorImportExcelVO.class); + return success(vendorService.importVendorList(list, updateSupport)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java new file mode 100644 index 000000000..44aaa35cc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 供应商 Excel 导入 VO + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MesMdVendorImportExcelVO { + + @ExcelProperty("供应商编码") + private String code; + + @ExcelProperty("供应商名称") + private String name; + + @ExcelProperty("供应商简称") + private String nickname; + + @ExcelProperty(value = "供应商等级", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_VENDOR_LEVEL) + private String level; + + @ExcelProperty("供应商电话") + private String telephone; + + @ExcelProperty("供应商邮箱地址") + private String email; + + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS) + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportRespVO.java new file mode 100644 index 000000000..92b552ec9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Schema(description = "管理后台 - MES 供应商导入 Response VO") +@Data +@Builder +public class MesMdVendorImportRespVO { + + @Schema(description = "创建成功的供应商编码数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List createCodes; + + @Schema(description = "更新成功的供应商编码数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List updateCodes; + + @Schema(description = "导入失败的供应商集合,key 为供应商编码,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) + private Map failureCodes; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorPageReqVO.java new file mode 100644 index 000000000..738b93ca4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 供应商分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdVendorPageReqVO extends PageParam { + + @Schema(description = "供应商编码", example = "V00101") + private String code; + + @Schema(description = "供应商名称", example = "海力德") + private String name; + + @Schema(description = "供应商简称", example = "海力德") + private String nickname; + + @Schema(description = "供应商英文名称", example = "HLD") + private String englishName; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java new file mode 100644 index 000000000..00450cced --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java @@ -0,0 +1,111 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 供应商 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdVendorRespVO { + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("供应商编号") + private Long id; + + @Schema(description = "供应商编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "V00101") + @ExcelProperty("供应商编码") + private String code; + + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "海力德电子") + @ExcelProperty("供应商名称") + private String name; + + @Schema(description = "供应商简称", example = "海力德") + @ExcelProperty("供应商简称") + private String nickname; + + @Schema(description = "供应商英文名称", example = "HLD Electronics") + @ExcelProperty("供应商英文名称") + private String englishName; + + @Schema(description = "供应商简介", example = "专业从事电子元器件生产与销售") + @ExcelProperty("供应商简介") + private String description; + + @Schema(description = "供应商LOGO地址", example = "https://xxx.com/logo.png") + private String logo; + + @Schema(description = "供应商等级", example = "A") + @ExcelProperty(value = "供应商等级", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_VENDOR_LEVEL) + private String level; + + @Schema(description = "供应商评分", example = "95") + @ExcelProperty("供应商评分") + private Integer score; + + @Schema(description = "供应商地址", example = "深圳市宝安区") + @ExcelProperty("供应商地址") + private String address; + + @Schema(description = "供应商官网地址", example = "https://www.hld-elec.com") + @ExcelProperty("供应商官网地址") + private String website; + + @Schema(description = "供应商邮箱地址", example = "info@hld-elec.com") + @ExcelProperty("供应商邮箱地址") + private String email; + + @Schema(description = "供应商电话", example = "0755-12345678") + @ExcelProperty("供应商电话") + private String telephone; + + @Schema(description = "联系人1", example = "王经理") + @ExcelProperty("联系人1") + private String contact1Name; + + @Schema(description = "联系人1-电话", example = "13800138001") + @ExcelProperty("联系人1-电话") + private String contact1Telephone; + + @Schema(description = "联系人1-邮箱", example = "wang@hld-elec.com") + @ExcelProperty("联系人1-邮箱") + private String contact1Email; + + @Schema(description = "联系人2", example = "赵助理") + @ExcelProperty("联系人2") + private String contact2Name; + + @Schema(description = "联系人2-电话", example = "13800138002") + @ExcelProperty("联系人2-电话") + private String contact2Telephone; + + @Schema(description = "联系人2-邮箱", example = "zhao@hld-elec.com") + @ExcelProperty("联系人2-邮箱") + private String contact2Email; + + @Schema(description = "统一社会信用代码", example = "91440300MA5EXAMPLE") + @ExcelProperty("统一社会信用代码") + private String creditCode; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java new file mode 100644 index 000000000..1a95f40c2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 供应商新增/修改 Request VO") +@Data +public class MesMdVendorSaveReqVO { + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "供应商编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "V00101") + @NotEmpty(message = "供应商编码不能为空") + private String code; + + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "海力德电子") + @NotEmpty(message = "供应商名称不能为空") + private String name; + + @Schema(description = "供应商简称", example = "海力德") + private String nickname; + + @Schema(description = "供应商英文名称", example = "HLD Electronics") + private String englishName; + + @Schema(description = "供应商简介", example = "专业从事电子元器件生产与销售") + private String description; + + @Schema(description = "供应商LOGO地址", example = "https://xxx.com/logo.png") + private String logo; + + @Schema(description = "供应商等级", example = "A") + private String level; + + @Schema(description = "供应商评分", example = "95") + private Integer score; + + @Schema(description = "供应商地址", example = "深圳市宝安区") + private String address; + + @Schema(description = "供应商官网地址", example = "https://www.hld-elec.com") + private String website; + + @Schema(description = "供应商邮箱地址", example = "info@hld-elec.com") + private String email; + + @Schema(description = "供应商电话", example = "0755-12345678") + private String telephone; + + @Schema(description = "联系人1", example = "王经理") + private String contact1Name; + + @Schema(description = "联系人1-电话", example = "13800138001") + private String contact1Telephone; + + @Schema(description = "联系人1-邮箱", example = "wang@hld-elec.com") + private String contact1Email; + + @Schema(description = "联系人2", example = "赵助理") + private String contact2Name; + + @Schema(description = "联系人2-电话", example = "13800138002") + private String contact2Telephone; + + @Schema(description = "联系人2-邮箱", example = "zhao@hld-elec.com") + private String contact2Email; + + @Schema(description = "统一社会信用代码", example = "91440300MA5EXAMPLE") + private String creditCode; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkshopController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkshopController.java new file mode 100644 index 000000000..ff825f7c1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkshopController.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.md.workstation.vo.workshop.MesMdWorkshopPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkshopService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.*; + +@Tag(name = "管理后台 - MES 车间") +@RestController +@RequestMapping("/mes/md-workshop") +@Validated +public class MesMdWorkshopController { + + @Resource + private MesMdWorkshopService workshopService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建车间") + @PreAuthorize("@ss.hasPermission('mes:md-workshop:create')") + public CommonResult createWorkshop(@Valid @RequestBody MesMdWorkshopSaveReqVO createReqVO) { + return success(workshopService.createWorkshop(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新车间") + @PreAuthorize("@ss.hasPermission('mes:md-workshop:update')") + public CommonResult updateWorkshop(@Valid @RequestBody MesMdWorkshopSaveReqVO updateReqVO) { + workshopService.updateWorkshop(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除车间") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-workshop:delete')") + public CommonResult deleteWorkshop(@RequestParam("id") Long id) { + workshopService.deleteWorkshop(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得车间") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-workshop:query')") + public CommonResult getWorkshop(@RequestParam("id") Long id) { + MesMdWorkshopDO workshop = workshopService.getWorkshop(id); + return success(BeanUtils.toBean(workshop, MesMdWorkshopRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得车间分页") + @PreAuthorize("@ss.hasPermission('mes:md-workshop:query')") + public CommonResult> getWorkshopPage(@Valid MesMdWorkshopPageReqVO pageReqVO) { + PageResult pageResult = workshopService.getWorkshopPage(pageReqVO); + return success(new PageResult<>(buildWorkshopRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得车间精简列表", description = "只包含被开启的车间,主要用于前端的下拉选项") + public CommonResult> getWorkshopSimpleList() { + List list = workshopService.getWorkshopListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, ws -> new MesMdWorkshopRespVO() + .setId(ws.getId()).setCode(ws.getCode()).setName(ws.getName()).setArea(ws.getArea()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出车间 Excel") + @PreAuthorize("@ss.hasPermission('mes:md-workshop:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportWorkshopExcel(@Valid MesMdWorkshopPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = workshopService.getWorkshopPage(pageReqVO).getList(); + List voList = buildWorkshopRespVOList(list); + ExcelUtils.write(response, "车间.xls", "数据", MesMdWorkshopRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + private List buildWorkshopRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取负责人信息 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesMdWorkshopDO::getChargeUserId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesMdWorkshopRespVO.class, vo -> { + MapUtils.findAndThen(userMap, vo.getChargeUserId(), + user -> vo.setChargeUserName(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationController.java new file mode 100644 index 000000000..b57369d26 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationController.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.md.workstation.vo.MesMdWorkstationPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkshopService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +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.*; + +@Tag(name = "管理后台 - MES 工作站") +@RestController +@RequestMapping("/mes/md-workstation") +@Validated +public class MesMdWorkstationController { + + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesMdWorkshopService workshopService; + @Resource + private MesProProcessService processService; + + @PostMapping("/create") + @Operation(summary = "创建工作站") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:create')") + public CommonResult createWorkstation(@Valid @RequestBody MesMdWorkstationSaveReqVO createReqVO) { + return success(workstationService.createWorkstation(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工作站") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult updateWorkstation(@Valid @RequestBody MesMdWorkstationSaveReqVO updateReqVO) { + workstationService.updateWorkstation(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工作站") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-workstation:delete')") + public CommonResult deleteWorkstation(@RequestParam("id") Long id) { + workstationService.deleteWorkstation(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工作站") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:query')") + public CommonResult getWorkstation(@RequestParam("id") Long id) { + MesMdWorkstationDO workstation = workstationService.getWorkstation(id); + return success(BeanUtils.toBean(workstation, MesMdWorkstationRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得工作站分页") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:query')") + public CommonResult> getWorkstationPage(@Valid MesMdWorkstationPageReqVO pageReqVO) { + PageResult pageResult = workstationService.getWorkstationPage(pageReqVO); + return success(new PageResult<>(buildWorkstationRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + + @GetMapping("/export-excel") + @Operation(summary = "导出工作站 Excel") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportWorkstationExcel(@Valid MesMdWorkstationPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = workstationService.getWorkstationPage(pageReqVO).getList(); + List voList = buildWorkstationRespVOList(list); + ExcelUtils.write(response, "工作站.xls", "数据", MesMdWorkstationRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + @SuppressWarnings("CodeBlock2Expr") + private List buildWorkstationRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取车间、工序信息 + Map workshopMap = workshopService.getWorkshopMap( + convertSet(list, MesMdWorkstationDO::getWorkshopId)); + Map processMap = processService.getProcessMap( + convertSet(list, MesMdWorkstationDO::getProcessId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesMdWorkstationRespVO.class, vo -> { + MapUtils.findAndThen(workshopMap, vo.getWorkshopId(), + workshop -> vo.setWorkshopName(workshop.getName())); + MapUtils.findAndThen(processMap, vo.getProcessId(), + process -> vo.setProcessName(process.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationMachineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationMachineController.java new file mode 100644 index 000000000..1e0a77b2c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationMachineController.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.machine.MesMdWorkstationMachineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.machine.MesMdWorkstationMachineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationMachineDO; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationMachineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 设备资源") +@RestController +@RequestMapping("/mes/md-workstation-machine") +@Validated +public class MesMdWorkstationMachineController { + + @Resource + private MesMdWorkstationMachineService workstationMachineService; + + @Resource + private MesDvMachineryService machineryService; + + @PostMapping("/create") + @Operation(summary = "创建设备资源") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult createWorkstationMachine(@Valid @RequestBody MesMdWorkstationMachineSaveReqVO createReqVO) { + return success(workstationMachineService.createWorkstationMachine(createReqVO)); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除设备资源") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult deleteWorkstationMachine(@RequestParam("id") Long id) { + workstationMachineService.deleteWorkstationMachine(id); + return success(true); + } + + @GetMapping("/list-by-workstation") + @Operation(summary = "获得设备资源列表") + @Parameter(name = "workstationId", description = "工作站编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-workstation:query')") + public CommonResult> getWorkstationMachineList( + @RequestParam("workstationId") Long workstationId) { + List list = workstationMachineService.getWorkstationMachineListByWorkstationId(workstationId); + return success(buildWorkstationMachineRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildWorkstationMachineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取设备信息 + Map machineryMap = machineryService.getMachineryMap( + convertSet(list, MesMdWorkstationMachineDO::getMachineryId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesMdWorkstationMachineRespVO.class, vo -> { + MapUtils.findAndThen(machineryMap, vo.getMachineryId(), + machinery -> vo.setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationToolController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationToolController.java new file mode 100644 index 000000000..36fee755c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationToolController.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.tool.MesMdWorkstationToolRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.tool.MesMdWorkstationToolSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationToolDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolTypeDO; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationToolService; +import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 工装夹具资源") +@RestController +@RequestMapping("/mes/md-workstation-tool") +@Validated +public class MesMdWorkstationToolController { + + @Resource + private MesMdWorkstationToolService workstationToolService; + + @Resource + private MesTmToolTypeService toolTypeService; + + @PostMapping("/create") + @Operation(summary = "创建工装夹具资源") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult createWorkstationTool(@Valid @RequestBody MesMdWorkstationToolSaveReqVO createReqVO) { + return success(workstationToolService.createWorkstationTool(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工装夹具资源") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult updateWorkstationTool(@Valid @RequestBody MesMdWorkstationToolSaveReqVO updateReqVO) { + workstationToolService.updateWorkstationTool(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工装夹具资源") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult deleteWorkstationTool(@RequestParam("id") Long id) { + workstationToolService.deleteWorkstationTool(id); + return success(true); + } + + @GetMapping("/list-by-workstation") + @Operation(summary = "获得工装夹具资源列表") + @Parameter(name = "workstationId", description = "工作站编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-workstation:query')") + public CommonResult> getWorkstationToolList( + @RequestParam("workstationId") Long workstationId) { + List list = workstationToolService.getWorkstationToolListByWorkstationId(workstationId); + return success(buildWorkstationToolRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildWorkstationToolRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取工具类型信息 + Map toolTypeMap = toolTypeService.getToolTypeMap( + convertSet(list, MesMdWorkstationToolDO::getToolTypeId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesMdWorkstationToolRespVO.class, vo -> + MapUtils.findAndThen(toolTypeMap, vo.getToolTypeId(), + toolType -> vo.setToolTypeName(toolType.getName()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationWorkerController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationWorkerController.java new file mode 100644 index 000000000..2bf066dcd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkstationWorkerController.java @@ -0,0 +1,91 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.worker.MesMdWorkstationWorkerRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.worker.MesMdWorkstationWorkerSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationWorkerDO; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationWorkerService; +import cn.iocoder.yudao.module.system.api.dept.PostApi; +import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 人力资源") +@RestController +@RequestMapping("/mes/md-workstation-worker") +@Validated +public class MesMdWorkstationWorkerController { + + @Resource + private MesMdWorkstationWorkerService workstationWorkerService; + + @Resource + private PostApi postApi; + + @PostMapping("/create") + @Operation(summary = "创建人力资源") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult createWorkstationWorker(@Valid @RequestBody MesMdWorkstationWorkerSaveReqVO createReqVO) { + return success(workstationWorkerService.createWorkstationWorker(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新人力资源") + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult updateWorkstationWorker(@Valid @RequestBody MesMdWorkstationWorkerSaveReqVO updateReqVO) { + workstationWorkerService.updateWorkstationWorker(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除人力资源") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-workstation:update')") + public CommonResult deleteWorkstationWorker(@RequestParam("id") Long id) { + workstationWorkerService.deleteWorkstationWorker(id); + return success(true); + } + + @GetMapping("/list-by-workstation") + @Operation(summary = "获得人力资源列表") + @Parameter(name = "workstationId", description = "工作站编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-workstation:query')") + public CommonResult> getWorkstationWorkerList( + @RequestParam("workstationId") Long workstationId) { + List list = workstationWorkerService.getWorkstationWorkerListByWorkstationId(workstationId); + return success(buildWorkstationWorkerRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildWorkstationWorkerRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取岗位信息 + Map postMap = postApi.getPostMap( + convertSet(list, MesMdWorkstationWorkerDO::getPostId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesMdWorkstationWorkerRespVO.class, vo -> { + MapUtils.findAndThen(postMap, vo.getPostId(), + post -> vo.setPostName(post.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationPageReqVO.java new file mode 100644 index 000000000..90d3281a7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 工作站分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdWorkstationPageReqVO extends PageParam { + + @Schema(description = "工作站编码", example = "WK001") + private String code; + + @Schema(description = "工作站名称", example = "一号工作站") + private String name; + + @Schema(description = "所在车间编号", example = "1") + private Long workshopId; + + @Schema(description = "工序编号", example = "1") + private Long processId; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationRespVO.java new file mode 100644 index 000000000..ef65dea24 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationRespVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工作站 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdWorkstationRespVO { + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("工作站编号") + private Long id; + + @Schema(description = "工作站编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WK001") + @ExcelProperty("工作站编码") + private String code; + + @Schema(description = "工作站名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "一号工作站") + @ExcelProperty("工作站名称") + private String name; + + @Schema(description = "工作站地点", example = "A区1号线") + @ExcelProperty("工作站地点") + private String address; + + @Schema(description = "所在车间编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long workshopId; + + @Schema(description = "车间名称", example = "一号车间") + @ExcelProperty("车间名称") + private String workshopName; + + @Schema(description = "工序编号", example = "1") + private Long processId; + + @Schema(description = "工序名称", example = "打磨") + @ExcelProperty("工序名称") + private String processName; + + @Schema(description = "线边库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationSaveReqVO.java new file mode 100644 index 000000000..e0beeaa2b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationSaveReqVO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 工作站新增/修改 Request VO") +@Data +public class MesMdWorkstationSaveReqVO { + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "工作站编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WK001") + @NotEmpty(message = "工作站编码不能为空") + private String code; + + @Schema(description = "工作站名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "一号工作站") + @NotEmpty(message = "工作站名称不能为空") + private String name; + + @Schema(description = "工作站地点", example = "A区1号线") + private String address; + + @Schema(description = "所在车间编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "所在车间不能为空") + private Long workshopId; + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "所属工序不能为空") + private Long processId; + + @Schema(description = "线边库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/machine/MesMdWorkstationMachineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/machine/MesMdWorkstationMachineRespVO.java new file mode 100644 index 000000000..f4ac4f5a3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/machine/MesMdWorkstationMachineRespVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.machine; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 设备资源 Response VO") +@Data +public class MesMdWorkstationMachineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long workstationId; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long machineryId; + + @Schema(description = "设备编码", example = "M001") + private String machineryCode; + + @Schema(description = "设备名称", example = "CNC数控机床") + private String machineryName; + + @Schema(description = "数量", example = "1") + private Integer quantity; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/machine/MesMdWorkstationMachineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/machine/MesMdWorkstationMachineSaveReqVO.java new file mode 100644 index 000000000..94203c1f8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/machine/MesMdWorkstationMachineSaveReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.machine; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 设备资源新增 Request VO") +@Data +public class MesMdWorkstationMachineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工作站不能为空") + private Long workstationId; + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "设备不能为空") + private Long machineryId; + + @Schema(description = "数量", example = "1") + private Integer quantity; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/tool/MesMdWorkstationToolRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/tool/MesMdWorkstationToolRespVO.java new file mode 100644 index 000000000..e4dbf5739 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/tool/MesMdWorkstationToolRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.tool; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工装夹具资源 Response VO") +@Data +public class MesMdWorkstationToolRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long workstationId; + + @Schema(description = "工具类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long toolTypeId; + + @Schema(description = "工具类型名称", example = "钻头") + private String toolTypeName; + + @Schema(description = "数量", example = "1") + private Integer quantity; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/tool/MesMdWorkstationToolSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/tool/MesMdWorkstationToolSaveReqVO.java new file mode 100644 index 000000000..15f60a0b2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/tool/MesMdWorkstationToolSaveReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.tool; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 工装夹具资源新增/修改 Request VO") +@Data +public class MesMdWorkstationToolSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工作站不能为空") + private Long workstationId; + + @Schema(description = "工具类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工具类型不能为空") + private Long toolTypeId; + + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "数量不能为空") + private Integer quantity; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/worker/MesMdWorkstationWorkerRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/worker/MesMdWorkstationWorkerRespVO.java new file mode 100644 index 000000000..31340d334 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/worker/MesMdWorkstationWorkerRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.worker; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 人力资源 Response VO") +@Data +public class MesMdWorkstationWorkerRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long workstationId; + + @Schema(description = "岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long postId; + + @Schema(description = "岗位名称", example = "操作员") + private String postName; + + @Schema(description = "数量", example = "1") + private Integer quantity; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/worker/MesMdWorkstationWorkerSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/worker/MesMdWorkstationWorkerSaveReqVO.java new file mode 100644 index 000000000..89579f8a7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/worker/MesMdWorkstationWorkerSaveReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.worker; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 人力资源新增/修改 Request VO") +@Data +public class MesMdWorkstationWorkerSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工作站不能为空") + private Long workstationId; + + @Schema(description = "岗位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "岗位不能为空") + private Long postId; + + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "数量不能为空") + private Integer quantity; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopPageReqVO.java new file mode 100644 index 000000000..cefa301e3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 车间分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdWorkshopPageReqVO extends PageParam { + + @Schema(description = "车间编码", example = "WS001") + private String code; + + @Schema(description = "车间名称", example = "一号车间") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopRespVO.java new file mode 100644 index 000000000..a04043cc8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 车间 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdWorkshopRespVO { + + @Schema(description = "车间编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("车间编号") + private Long id; + + @Schema(description = "车间编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WS001") + @ExcelProperty("车间编码") + private String code; + + @Schema(description = "车间名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "一号车间") + @ExcelProperty("车间名称") + private String name; + + @Schema(description = "面积", example = "1000.00") + @ExcelProperty("面积") + private BigDecimal area; + + @Schema(description = "负责人用户编号", example = "1") + private Long chargeUserId; + + @Schema(description = "负责人名称", example = "张三") + @ExcelProperty("负责人") + private String chargeUserName; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopSaveReqVO.java new file mode 100644 index 000000000..148596201 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopSaveReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 车间新增/修改 Request VO") +@Data +public class MesMdWorkshopSaveReqVO { + + @Schema(description = "车间编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "车间编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WS001") + @NotEmpty(message = "车间编码不能为空") + private String code; + + @Schema(description = "车间名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "一号车间") + @NotEmpty(message = "车间名称不能为空") + private String name; + + @Schema(description = "面积", example = "1000.00") + private BigDecimal area; + + @Schema(description = "负责人用户编号", example = "1") + private Long chargeUserId; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/MesProAndonConfigController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/MesProAndonConfigController.java new file mode 100644 index 000000000..651838050 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/MesProAndonConfigController.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config.MesProAndonConfigPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config.MesProAndonConfigRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config.MesProAndonConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonConfigDO; +import cn.iocoder.yudao.module.mes.service.pro.andon.MesProAndonConfigService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 安灯呼叫配置") +@RestController +@RequestMapping("/mes/pro/andon-config") +@Validated +public class MesProAndonConfigController { + + @Resource + private MesProAndonConfigService andonConfigService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建安灯呼叫配置") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-config:create')") + public CommonResult createAndonConfig(@Valid @RequestBody MesProAndonConfigSaveReqVO createReqVO) { + return success(andonConfigService.createAndonConfig(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新安灯呼叫配置") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-config:update')") + public CommonResult updateAndonConfig(@Valid @RequestBody MesProAndonConfigSaveReqVO updateReqVO) { + andonConfigService.updateAndonConfig(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除安灯呼叫配置") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-andon-config:delete')") + public CommonResult deleteAndonConfig(@RequestParam("id") Long id) { + andonConfigService.deleteAndonConfig(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得安灯呼叫配置") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-config:query')") + public CommonResult getAndonConfig(@RequestParam("id") Long id) { + MesProAndonConfigDO config = andonConfigService.getAndonConfig(id); + if (config == null) { + return success(null); + } + return success(buildConfigRespVOList(List.of(config)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得安灯呼叫配置分页") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-config:query')") + public CommonResult> getAndonConfigPage(@Valid MesProAndonConfigPageReqVO pageReqVO) { + PageResult pageResult = andonConfigService.getAndonConfigPage(pageReqVO); + return success(new PageResult<>(buildConfigRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/list") + @Operation(summary = "获得安灯呼叫配置列表") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-config:query')") + public CommonResult> getAndonConfigList() { + List list = andonConfigService.getAndonConfigList(); + return success(buildConfigRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildConfigRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesProAndonConfigDO::getHandlerUserId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProAndonConfigRespVO.class, vo -> + MapUtils.findAndThen(userMap, vo.getHandlerUserId(), + user -> vo.setHandlerUserNickname(user.getNickname()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/MesProAndonRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/MesProAndonRecordController.java new file mode 100644 index 000000000..314ca40ec --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/MesProAndonRecordController.java @@ -0,0 +1,151 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.andon.vo.record.MesProAndonRecordUpdateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordCreateReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.andon.MesProAndonRecordService; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Stream; + +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.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; + +@Tag(name = "管理后台 - MES 安灯呼叫记录") +@RestController +@RequestMapping("/mes/pro/andon-record") +@Validated +public class MesProAndonRecordController { + + @Resource + private MesProAndonRecordService andonRecordService; + + @Resource + private MesMdWorkstationService workstationService; + + @Resource + private MesProWorkOrderService workOrderService; + + @Resource + private MesProProcessService processService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建安灯呼叫记录") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-record:create')") + public CommonResult createAndonRecord(@Valid @RequestBody MesProAndonRecordCreateReqVO createReqVO) { + return success(andonRecordService.createAndonRecord(createReqVO)); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除安灯呼叫记录") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-andon-record:delete')") + public CommonResult deleteAndonRecord(@RequestParam("id") Long id) { + andonRecordService.deleteAndonRecord(id); + return success(true); + } + + @PutMapping("/update") + @Operation(summary = "更新安灯呼叫记录") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-record:update')") + public CommonResult updateAndonRecord(@Valid @RequestBody MesProAndonRecordUpdateReqVO updateReqVO) { + andonRecordService.updateAndonRecord(updateReqVO); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得安灯呼叫记录") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-record:query')") + public CommonResult getAndonRecord(@RequestParam("id") Long id) { + MesProAndonRecordDO record = andonRecordService.getAndonRecord(id); + if (record == null) { + return success(null); + } + return success(buildRecordRespVOList(List.of(record)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得安灯呼叫记录分页") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-record:query')") + public CommonResult> getAndonRecordPage(@Valid MesProAndonRecordPageReqVO pageReqVO) { + PageResult pageResult = andonRecordService.getAndonRecordPage(pageReqVO); + return success(new PageResult<>(buildRecordRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出安灯呼叫记录 Excel") + @PreAuthorize("@ss.hasPermission('mes:pro-andon-record:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportAndonRecordExcel(@Valid MesProAndonRecordPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = andonRecordService.getAndonRecordPage(pageReqVO).getList(); + List voList = buildRecordRespVOList(list); + ExcelUtils.write(response, "安灯呼叫记录.xls", "数据", MesProAndonRecordRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + private List buildRecordRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesProAndonRecordDO::getWorkstationId)); + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesProAndonRecordDO::getWorkOrderId)); + Map processMap = processService.getProcessMap( + new ArrayList<>(convertSet(list, MesProAndonRecordDO::getProcessId))); + Map userMap = adminUserApi.getUserMap(convertSetByFlatMap(list, + record -> Stream.of(record.getUserId(), record.getHandlerUserId()))); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProAndonRecordRespVO.class, vo -> { + MapUtils.findAndThen(workstationMap, vo.getWorkstationId(), ws -> + vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName())); + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), + wo -> vo.setWorkOrderCode(wo.getCode())); + MapUtils.findAndThen(processMap, vo.getProcessId(), + process -> vo.setProcessName(process.getName())); + MapUtils.findAndThen(userMap, vo.getUserId(), + user -> vo.setUserNickname(user.getNickname())); + MapUtils.findAndThen(userMap, vo.getHandlerUserId(), + user -> vo.setHandlerUserNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigPageReqVO.java new file mode 100644 index 000000000..d2ca9f6b9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 安灯呼叫配置分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProAndonConfigPageReqVO extends PageParam { + + @Schema(description = "呼叫原因", example = "设备故障") + private String reason; + + @Schema(description = "级别", example = "1") + private Integer level; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigRespVO.java new file mode 100644 index 000000000..ed1e54130 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigRespVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 安灯呼叫配置 Response VO") +@Data +public class MesProAndonConfigRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "呼叫原因", example = "设备故障") + private String reason; + + @Schema(description = "级别", example = "1") + private Integer level; + + @Schema(description = "处置人角色编号", example = "10") + private Long handlerRoleId; + + @Schema(description = "处置人编号", example = "100") + private Long handlerUserId; + + @Schema(description = "处置人昵称", example = "张三") + private String handlerUserNickname; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigSaveReqVO.java new file mode 100644 index 000000000..7ac339747 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/config/MesProAndonConfigSaveReqVO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 安灯呼叫配置新增/修改 Request VO") +@Data +public class MesProAndonConfigSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "呼叫原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "设备故障") + @NotEmpty(message = "呼叫原因不能为空") + private String reason; + + @Schema(description = "级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "级别不能为空") + private Integer level; + + @Schema(description = "处置人角色编号", example = "10") + private Long handlerRoleId; + + @Schema(description = "处置人编号", example = "100") + private Long handlerUserId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordCreateReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordCreateReqVO.java new file mode 100644 index 000000000..78df9841c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordCreateReqVO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 安灯呼叫记录新增 Request VO") +@Data +public class MesProAndonRecordCreateReqVO { + + @Schema(description = "安灯配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "安灯配置不能为空") + private Long configId; + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "工作站不能为空") + private Long workstationId; + + @Schema(description = "发起用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "发起用户不能为空") + private Long userId; + + @Schema(description = "生产工单编号", example = "200") + private Long workOrderId; + + @Schema(description = "工序编号", example = "300") + private Long processId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordPageReqVO.java new file mode 100644 index 000000000..2b45ee9a1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 安灯呼叫记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProAndonRecordPageReqVO extends PageParam { + + @Schema(description = "工作站编号", example = "100") + private Long workstationId; + + @Schema(description = "发起用户编号", example = "1") + private Long userId; + + @Schema(description = "处置人编号", example = "1") + private Long handlerUserId; + + @Schema(description = "处置状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordRespVO.java new file mode 100644 index 000000000..ef5afa70e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordRespVO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 安灯呼叫记录 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesProAndonRecordRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "安灯配置编号", example = "1") + private Long configId; + + @Schema(description = "工作站编号", example = "100") + private Long workstationId; + + @Schema(description = "工作站编码", example = "WS-001") + @ExcelProperty("工作站编码") + private String workstationCode; + + @Schema(description = "工作站名称", example = "工作站 A") + @ExcelProperty("工作站名称") + private String workstationName; + + @Schema(description = "发起用户编号", example = "1") + private Long userId; + + @Schema(description = "发起人昵称", example = "张三") + @ExcelProperty("发起人") + private String userNickname; + + @Schema(description = "生产工单编号", example = "200") + private Long workOrderId; + + @Schema(description = "工单编码", example = "WO-001") + @ExcelProperty("工单编码") + private String workOrderCode; + + @Schema(description = "工序编号", example = "300") + private Long processId; + + @Schema(description = "工序名称", example = "组装工序") + @ExcelProperty("工序名称") + private String processName; + + @Schema(description = "呼叫原因", example = "设备故障") + @ExcelProperty("呼叫原因") + private String reason; + + @Schema(description = "级别", example = "1") + @ExcelProperty(value = "级别", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_PRO_ANDON_LEVEL) + private Integer level; + + @Schema(description = "处置状态", example = "0") + @ExcelProperty(value = "处置状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_PRO_ANDON_STATUS) + private Integer status; + + @Schema(description = "处置时间") + @ExcelProperty("处置时间") + private LocalDateTime handleTime; + + @Schema(description = "处置人编号", example = "100") + private Long handlerUserId; + + @Schema(description = "处置人昵称", example = "李四") + @ExcelProperty("处置人") + private String handlerUserNickname; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("发起时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordUpdateReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordUpdateReqVO.java new file mode 100644 index 000000000..61f3db10d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordUpdateReqVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record; + +import cn.iocoder.yudao.module.mes.enums.pro.MesProAndonStatusEnum; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 安灯呼叫记录更新 Request VO") +@Data +public class MesProAndonRecordUpdateReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "编号不能为空") + private Long id; + + @Schema(description = "处置时间") + private LocalDateTime handleTime; + + @Schema(description = "处置人编号", example = "100") + private Long handlerUserId; + + @Schema(description = "备注", example = "已修复") + private String remark; + + @Schema(description = "处置状态", example = "1") + @NotNull(message = "处置状态不能为空") + private Integer status; + + @AssertTrue(message = "标记已处置时,处置时间不能为空") + @JsonIgnore + public boolean isHandleTimeValid() { + if (!MesProAndonStatusEnum.HANDLED.getStatus().equals(status)) { + return true; + } + return handleTime != null; + } + + @AssertTrue(message = "标记已处置时,处置人不能为空") + @JsonIgnore + public boolean isHandlerUserIdValid() { + if (!MesProAndonStatusEnum.HANDLED.getStatus().equals(status)) { + return true; + } + return handlerUserId != null; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardController.java new file mode 100644 index 000000000..9481d82bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardController.java @@ -0,0 +1,175 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.card; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.card.vo.MesProCardPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardSaveReqVO; +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.card.MesProCardDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +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.card.MesProCardService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 生产流转卡") +@RestController +@RequestMapping("/mes/pro/card") +@Validated +public class MesProCardController { + + @Resource + private MesProCardService cardService; + + @Resource + private MesProWorkOrderService workOrderService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建生产流转卡") + @PreAuthorize("@ss.hasPermission('mes:pro-card:create')") + public CommonResult createCard(@Valid @RequestBody MesProCardSaveReqVO createReqVO) { + return success(cardService.createCard(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新生产流转卡") + @PreAuthorize("@ss.hasPermission('mes:pro-card:update')") + public CommonResult updateCard(@Valid @RequestBody MesProCardSaveReqVO updateReqVO) { + cardService.updateCard(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产流转卡") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-card:delete')") + public CommonResult deleteCard(@RequestParam("id") Long id) { + cardService.deleteCard(id); + return success(true); + } + + @PutMapping("/submit") + @Operation(summary = "提交生产流转卡") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-card:update')") + public CommonResult submitCard(@RequestParam("id") Long id) { + cardService.submitCard(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成生产流转卡") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-card:finish')") + public CommonResult finishCard(@RequestParam("id") Long id) { + cardService.finishCard(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消生产流转卡") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-card:update')") + public CommonResult cancelCard(@RequestParam("id") Long id) { + cardService.cancelCard(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产流转卡") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-card:query')") + public CommonResult getCard(@RequestParam("id") Long id) { + MesProCardDO card = cardService.getCard(id); + if (card == null) { + return success(null); + } + return success(buildCardRespVOList(List.of(card)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得生产流转卡分页") + @PreAuthorize("@ss.hasPermission('mes:pro-card:query')") + public CommonResult> getCardPage(@Valid MesProCardPageReqVO pageReqVO) { + PageResult pageResult = cardService.getCardPage(pageReqVO); + return success(new PageResult<>(buildCardRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得生产流转卡精简列表", description = "主要用于前端的下拉选项") + public CommonResult> getCardSimpleList() { + List list = cardService.getCardSimpleList(); + return success(buildCardRespVOList(list)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出生产流转卡 Excel") + @PreAuthorize("@ss.hasPermission('mes:pro-card:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportCardExcel(@Valid MesProCardPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = cardService.getCardPage(pageReqVO).getList(); + List voList = buildCardRespVOList(list); + ExcelUtils.write(response, "生产流转卡.xls", "数据", MesProCardRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + private List buildCardRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesProCardDO::getWorkOrderId)); + Map itemMap = itemService.getItemMap( + convertSet(list, MesProCardDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProCardRespVO.class, vo -> { + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder -> + vo.setWorkOrderCode(workOrder.getCode()).setWorkOrderName(workOrder.getName())); + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()) + .setSpecification(item.getSpecification()).setUnitMeasureId(item.getUnitMeasureId()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardProcessController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardProcessController.java new file mode 100644 index 000000000..171e36d8b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardProcessController.java @@ -0,0 +1,121 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.card; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process.MesProCardProcessPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process.MesProCardProcessRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process.MesProCardProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.card.MesProCardProcessService; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 流转卡工序记录") +@RestController +@RequestMapping("/mes/pro/card-process") +@Validated +public class MesProCardProcessController { + + @Resource + private MesProCardProcessService cardProcessService; + + @Resource + private MesProProcessService processService; + + @Resource + private MesMdWorkstationService workstationService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建流转卡工序记录") + @PreAuthorize("@ss.hasPermission('mes:pro-card:create')") + public CommonResult createCardProcess(@Valid @RequestBody MesProCardProcessSaveReqVO createReqVO) { + return success(cardProcessService.createCardProcess(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新流转卡工序记录") + @PreAuthorize("@ss.hasPermission('mes:pro-card:update')") + public CommonResult updateCardProcess(@Valid @RequestBody MesProCardProcessSaveReqVO updateReqVO) { + cardProcessService.updateCardProcess(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除流转卡工序记录") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-card:delete')") + public CommonResult deleteCardProcess(@RequestParam("id") Long id) { + cardProcessService.deleteCardProcess(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得流转卡工序记录") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-card:query')") + public CommonResult getCardProcess(@RequestParam("id") Long id) { + MesProCardProcessDO cardProcess = cardProcessService.getCardProcess(id); + if (cardProcess == null) { + return success(null); + } + return success(buildCardProcessRespVOList(List.of(cardProcess)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得流转卡工序记录分页") + @PreAuthorize("@ss.hasPermission('mes:pro-card:query')") + public CommonResult> getCardProcessPage(@Valid MesProCardProcessPageReqVO pageReqVO) { + PageResult pageResult = cardProcessService.getCardProcessPage(pageReqVO); + return success(new PageResult<>(buildCardProcessRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildCardProcessRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map processMap = CollectionUtils.convertMap( + processService.getProcessList(new ArrayList<>(convertSet(list, MesProCardProcessDO::getProcessId))), + MesProProcessDO::getId); + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesProCardProcessDO::getWorkstationId)); + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesProCardProcessDO::getUserId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProCardProcessRespVO.class, vo -> { + MapUtils.findAndThen(processMap, vo.getProcessId(), process -> + vo.setProcessCode(process.getCode()).setProcessName(process.getName())); + MapUtils.findAndThen(workstationMap, vo.getWorkstationId(), ws -> + vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName())); + MapUtils.findAndThen(userMap, vo.getUserId(), + user -> vo.setNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardPageReqVO.java new file mode 100644 index 000000000..b4564dd9c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardPageReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 生产流转卡分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProCardPageReqVO extends PageParam { + + @Schema(description = "流转卡编码", example = "CARD-001") + private String code; + + @Schema(description = "生产工单编号", example = "100") + private Long workOrderId; + + @Schema(description = "产品物料编号", example = "200") + private Long itemId; + + @Schema(description = "批次号", example = "BATCH-001") + private String batchCode; + + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java new file mode 100644 index 000000000..59e2c7e68 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产流转卡 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesProCardRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "流转卡编码", example = "CARD-001") + @ExcelProperty("流转卡编码") + private String code; + + @Schema(description = "生产工单编号", example = "100") + private Long workOrderId; + + @Schema(description = "工单编码", example = "WO-001") + @ExcelProperty("工单编码") + private String workOrderCode; + + @Schema(description = "工单名称", example = "生产工单-A") + @ExcelProperty("工单名称") + private String workOrderName; + + @Schema(description = "批次号", example = "BATCH-001") + @ExcelProperty("批次号") + private String batchCode; + + @Schema(description = "产品物料编号", example = "200") + private Long itemId; + + @Schema(description = "产品编码", example = "P-001") + @ExcelProperty("产品编码") + private String itemCode; + + @Schema(description = "产品名称", example = "电路板 A") + @ExcelProperty("产品名称") + private String itemName; + + @Schema(description = "规格型号", example = "100x200mm") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "单位编号", example = "300") + private Long unitMeasureId; + + @Schema(description = "单位名称", example = "个") + @ExcelProperty("单位") + private String unitMeasureName; + + @Schema(description = "流转数量", example = "100.00") + @ExcelProperty("流转数量") + private BigDecimal transferedQuantity; + + @Schema(description = "状态", example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardSaveReqVO.java new file mode 100644 index 000000000..be96ca15c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardSaveReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 生产流转卡新增/修改 Request VO") +@Data +public class MesProCardSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "流转卡编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "CARD-001") + @NotEmpty(message = "流转卡编码不能为空") + private String code; + + @Schema(description = "生产工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "生产工单不能为空") + private Long workOrderId; + + @Schema(description = "批次号", example = "BATCH-001") + private String batchCode; + + @Schema(description = "产品物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + @NotNull(message = "产品物料不能为空") + private Long itemId; + + @Schema(description = "流转数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "流转数量不能为空") + private BigDecimal transferedQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessPageReqVO.java new file mode 100644 index 000000000..ee1e7ddb6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessPageReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 流转卡工序记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProCardProcessPageReqVO extends PageParam { + + @Schema(description = "流转卡编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "流转卡编号不能为空") + private Long cardId; + + @Schema(description = "工序编号", example = "200") + private Long processId; + + @Schema(description = "工位编号", example = "300") + private Long workstationId; + + @Schema(description = "操作人编号", example = "400") + private Long userId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessRespVO.java new file mode 100644 index 000000000..1a2d963c0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessRespVO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 流转卡工序记录 Response VO") +@Data +public class MesProCardProcessRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "流转卡编号", example = "100") + private Long cardId; + + @Schema(description = "序号", example = "1") + private Integer sort; + + @Schema(description = "工序编号", example = "200") + private Long processId; + + @Schema(description = "工序编码", example = "PROC-001") + private String processCode; + + @Schema(description = "工序名称", example = "焊接") + private String processName; + + @Schema(description = "进入工序时间") + private LocalDateTime inputTime; + + @Schema(description = "出工序时间") + private LocalDateTime outputTime; + + @Schema(description = "投入数量", example = "100.00") + private BigDecimal inputQuantity; + + @Schema(description = "产出数量", example = "98.00") + private BigDecimal outputQuantity; + + @Schema(description = "不合格品数量", example = "2.00") + private BigDecimal unqualifiedQuantity; + + @Schema(description = "工位编号", example = "300") + private Long workstationId; + + @Schema(description = "工位编码", example = "WS-001") + private String workstationCode; + + @Schema(description = "工位名称", example = "焊接工位 1") + private String workstationName; + + @Schema(description = "操作人编号", example = "400") + private Long userId; + + @Schema(description = "操作人名称", example = "张三") + private String nickname; + + @Schema(description = "过程检验单编号", example = "500") + private Long ipqcId; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessSaveReqVO.java new file mode 100644 index 000000000..3d2f29422 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/process/MesProCardProcessSaveReqVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 流转卡工序记录新增/修改 Request VO") +@Data +public class MesProCardProcessSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "流转卡编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "流转卡不能为空") + private Long cardId; + + @Schema(description = "序号", example = "1") + private Integer sort; + + @Schema(description = "工序编号", example = "200") + private Long processId; + + @Schema(description = "进入工序时间") + private LocalDateTime inputTime; + + @Schema(description = "出工序时间") + private LocalDateTime outputTime; + + @Schema(description = "投入数量", example = "100.00") + private BigDecimal inputQuantity; + + @Schema(description = "产出数量", example = "98.00") + private BigDecimal outputQuantity; + + @Schema(description = "不合格品数量", example = "2.00") + private BigDecimal unqualifiedQuantity; + + @Schema(description = "工位编号", example = "300") + private Long workstationId; + + @Schema(description = "操作人编号", example = "400") + private Long userId; + + @Schema(description = "过程检验单编号", example = "500") + private Long ipqcId; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java new file mode 100644 index 000000000..99dde54ae --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java @@ -0,0 +1,237 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.feedback; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.feedback.vo.MesProFeedbackPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackSaveReqVO; +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.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +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.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteService; +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Stream; + +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.*; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - MES 生产报工") +@RestController +@RequestMapping("/mes/pro/feedback") +@Validated +public class MesProFeedbackController { + + @Resource + private MesProFeedbackService feedbackService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesProRouteService routeService; + @Resource + private MesProProcessService processService; + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesProRouteProcessService routeProcessService; + @Resource + private MesProTaskService taskService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建生产报工") + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:create')") + public CommonResult createFeedback(@Valid @RequestBody MesProFeedbackSaveReqVO createReqVO) { + return success(feedbackService.createFeedback(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新生产报工") + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:update')") + public CommonResult updateFeedback(@Valid @RequestBody MesProFeedbackSaveReqVO updateReqVO) { + feedbackService.updateFeedback(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产报工") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:delete')") + public CommonResult deleteFeedback(@RequestParam("id") Long id) { + feedbackService.deleteFeedback(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产报工") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:query')") + public CommonResult getFeedback(@RequestParam("id") Long id) { + MesProFeedbackDO feedback = feedbackService.getFeedback(id); + if (feedback == null) { + return success(null); + } + return success(buildFeedbackRespVOList(List.of(feedback)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得生产报工分页") + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:query')") + public CommonResult> getFeedbackPage(@Valid MesProFeedbackPageReqVO pageReqVO) { + PageResult pageResult = feedbackService.getFeedbackPage(pageReqVO); + return success(new PageResult<>(buildFeedbackRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出生产报工 Excel") + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportFeedbackExcel(@Valid MesProFeedbackPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = feedbackService.getFeedbackPage(pageReqVO).getList(); + List voList = buildFeedbackRespVOList(list); + ExcelUtils.write(response, "生产报工.xls", "数据", MesProFeedbackRespVO.class, voList); + } + + @PutMapping("/submit") + @Operation(summary = "提交报工") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:update')") + public CommonResult submitFeedback(@RequestParam("id") Long id) { + feedbackService.submitFeedback(id); + return success(true); + } + + @PutMapping("/reject") + @Operation(summary = "驳回报工") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:update')") + public CommonResult rejectFeedback(@RequestParam("id") Long id) { + feedbackService.rejectFeedback(id); + return success(true); + } + + @PutMapping("/approve") + @Operation(summary = "审批报工") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:approve')") + public CommonResult approveFeedback(@RequestParam("id") Long id) { + return success(feedbackService.approveFeedback(id, getLoginUserId())); + } + + // ==================== 拼接 VO ==================== + + private List buildFeedbackRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1.1 任务(获取 taskCode) + Map taskMap = taskService.getTaskMap( + convertSet(list, MesProFeedbackDO::getTaskId)); + // 1.2 物料(直接从 DO.itemId)、计量单位(从 item.unitMeasureId) + Map itemMap = itemService.getItemMap( + convertSet(list, MesProFeedbackDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 1.3 工单 + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesProFeedbackDO::getWorkOrderId)); + // 1.4 工作站 + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesProFeedbackDO::getWorkstationId)); + // 1.5 工艺路线 + Set routeIds = convertSet(list, MesProFeedbackDO::getRouteId); + Map routeMap = routeService.getRouteMap(routeIds); + // 1.6 工序 + Map processMap = processService.getProcessMap( + new ArrayList<>(convertSet(list, MesProFeedbackDO::getProcessId))); + // 1.7 工序的 checkFlag:批量查询后直接构建 routeId -> processId -> checkFlag 的双层 Map + List allRouteProcesses = routeProcessService.getRouteProcessListByRouteIds(routeIds); + Map> routeProcessCheckFlagMap = new HashMap<>(); + for (MesProRouteProcessDO rp : allRouteProcesses) { + routeProcessCheckFlagMap + .computeIfAbsent(rp.getRouteId(), k -> new HashMap<>()) + .put(rp.getProcessId(), Boolean.TRUE.equals(rp.getCheckFlag())); + } + // 1.8 报工人/审核人 + Map userMap = adminUserApi.getUserMap( + convertSetByFlatMap(list, feedback -> + Stream.of(feedback.getFeedbackUserId(), feedback.getApproveUserId()))); + + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProFeedbackRespVO.class, vo -> { + // 工作站 + findAndThen(workstationMap, vo.getWorkstationId(), ws -> + vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName())); + // 工艺路线 + findAndThen(routeMap, vo.getRouteId(), route -> + vo.setRouteCode(route.getCode())); + // 工序 + findAndThen(processMap, vo.getProcessId(), process -> + vo.setProcessCode(process.getCode()).setProcessName(process.getName())); + // checkFlag + findAndThen(routeProcessCheckFlagMap, vo.getRouteId(), processCheckMap -> + findAndThen(processCheckMap, vo.getProcessId(), vo::setCheckFlag)); + // 工单 + findAndThen(workOrderMap, vo.getWorkOrderId(), wo -> + vo.setWorkOrderCode(wo.getCode()).setWorkOrderName(wo.getName())); + // 任务 + findAndThen(taskMap, vo.getTaskId(), task -> + vo.setTaskCode(task.getCode())); + // 物料 → 单位 + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()) + .setUnitMeasureId(item.getUnitMeasureId()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), unit -> + vo.setUnitMeasureName(unit.getName())); + }); + // 报工人、审核人 + findAndThen(userMap, vo.getFeedbackUserId(), user -> + vo.setFeedbackUserNickname(user.getNickname())); + findAndThen(userMap, vo.getApproveUserId(), user -> + vo.setApproveUserNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackPageReqVO.java new file mode 100644 index 000000000..8a8470e21 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackPageReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 生产报工分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProFeedbackPageReqVO extends PageParam { + + @Schema(description = "报工单编号", example = "FB202503") + private String code; + + @Schema(description = "报工类型", example = "1") + private Integer type; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "报工时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] feedbackTime; + + @Schema(description = "产品物料编号", example = "100") + private Long itemId; + + @Schema(description = "报工人编号", example = "1") + private Long feedbackUserId; + + @Schema(description = "记录人编号(创建人)", example = "1") + private String creator; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java new file mode 100644 index 000000000..b86dc24c5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java @@ -0,0 +1,172 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产报工 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesProFeedbackRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "报工单编号", example = "FB202503160001") + @ExcelProperty("报工单编号") + private String code; + + @Schema(description = "报工类型", example = "1") + @ExcelProperty(value = "报工类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_PRO_FEEDBACK_TYPE) + private Integer type; + + @Schema(description = "报工途径", example = "PC") + @ExcelProperty("报工途径") + private String channel; + + @Schema(description = "报工时间") + @ExcelProperty("报工时间") + private LocalDateTime feedbackTime; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "工作站编码", example = "WS-001") + @ExcelProperty("工作站编码") + private String workstationCode; + + @Schema(description = "工作站名称", example = "注塑工作站") + @ExcelProperty("工作站名称") + private String workstationName; + + @Schema(description = "工艺路线编号", example = "1") + private Long routeId; + + @Schema(description = "工艺路线编码", example = "RT-001") + private String routeCode; + + @Schema(description = "工序编号", example = "1") + private Long processId; + + @Schema(description = "工序编码", example = "PR-001") + @ExcelProperty("工序编码") + private String processCode; + + @Schema(description = "工序名称", example = "注塑") + @ExcelProperty("工序名称") + private String processName; + + @Schema(description = "是否需要检验") + private Boolean checkFlag; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "工单编码", example = "MO202503120008") + @ExcelProperty("工单编码") + private String workOrderCode; + + @Schema(description = "工单名称", example = "博世螺丝刀") + @ExcelProperty("工单名称") + private String workOrderName; + + @Schema(description = "生产任务编号", example = "1") + private Long taskId; + + @Schema(description = "任务编码", example = "PT202503150001") + private String taskCode; + + @Schema(description = "产品物料编号", example = "75") + private Long itemId; + + @Schema(description = "物料编码", example = "I-075") + @ExcelProperty("物料编码") + private String itemCode; + + @Schema(description = "物料名称", example = "博世螺丝刀") + @ExcelProperty("物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "一字型") + @ExcelProperty("规格型号") + private String itemSpecification; + + @Schema(description = "单位编号", example = "202") + private Long unitMeasureId; + + @Schema(description = "单位名称", example = "个") + @ExcelProperty("单位") + private String unitMeasureName; + + @Schema(description = "过期日期") + private LocalDateTime expireDate; + + @Schema(description = "生产批号", example = "LOT20260321") + private String lotNumber; + + @Schema(description = "排产数量", example = "5000.00") + @ExcelProperty("排产数量") + private BigDecimal scheduledQuantity; + + @Schema(description = "本次报工数量", example = "500.00") + @ExcelProperty("报工数量") + private BigDecimal feedbackQuantity; + + @Schema(description = "合格品数量", example = "490.00") + @ExcelProperty("合格品数量") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不良品数量", example = "10.00") + @ExcelProperty("不良品数量") + private BigDecimal unqualifiedQuantity; + + @Schema(description = "待检测数量", example = "0") + @ExcelProperty("待检测数量") + private BigDecimal uncheckQuantity; + + @Schema(description = "工废数量", example = "6.00") + private BigDecimal laborScrapQuantity; + + @Schema(description = "料废数量", example = "4.00") + private BigDecimal materialScrapQuantity; + + @Schema(description = "其他废品数量", example = "0") + private BigDecimal otherScrapQuantity; + + @Schema(description = "报工用户编号", example = "1") + private Long feedbackUserId; + + @Schema(description = "报工人昵称", example = "张三") + @ExcelProperty("报工人") + private String feedbackUserNickname; + + @Schema(description = "审核用户编号", example = "1") + private Long approveUserId; + + @Schema(description = "审核人昵称", example = "李四") + @ExcelProperty("审核人") + private String approveUserNickname; + + @Schema(description = "状态", example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_PRO_FEEDBACK_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackSaveReqVO.java new file mode 100644 index 000000000..e4c8a1566 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackSaveReqVO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产报工新增/修改 Request VO") +@Data +public class MesProFeedbackSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "报工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FB202503001") + @NotNull(message = "报工单编号不能为空") + private String code; + + @Schema(description = "报工类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "报工类型不能为空") + private Integer type; + + @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工作站不能为空") + private Long workstationId; + + @Schema(description = "工艺路线编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工艺路线不能为空") + private Long routeId; + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工序不能为空") + private Long processId; + + @Schema(description = "生产工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "生产工单不能为空") + private Long workOrderId; + + @Schema(description = "生产任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "生产任务不能为空") + private Long taskId; + + @Schema(description = "产品物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "产品物料不能为空") + private Long itemId; + + @Schema(description = "过期日期") + private LocalDateTime expireDate; + + @Schema(description = "生产批号", example = "LOT20260321") + private String lotNumber; + + @Schema(description = "排产数量", example = "5000.00") + private BigDecimal scheduledQuantity; + + @Schema(description = "本次报工数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00") + @NotNull(message = "报工数量不能为空") + private BigDecimal feedbackQuantity; + + @Schema(description = "合格品数量", example = "490.00") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不良品数量", example = "10.00") + private BigDecimal unqualifiedQuantity; + + @Schema(description = "待检测数量", example = "0") + private BigDecimal uncheckQuantity; + + @Schema(description = "工废数量", example = "6.00") + private BigDecimal laborScrapQuantity; + + @Schema(description = "料废数量", example = "4.00") + private BigDecimal materialScrapQuantity; + + @Schema(description = "其他废品数量", example = "0") + private BigDecimal otherScrapQuantity; + + @Schema(description = "报工人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "报工人不能为空") + private Long feedbackUserId; + + @Schema(description = "报工时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "报工时间不能为空") + private LocalDateTime feedbackTime; + + @Schema(description = "审核人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "审核人不能为空") + private Long approveUserId; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/package-info.java new file mode 100644 index 000000000..17a650db4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/package-info.java @@ -0,0 +1,4 @@ +/** + * MES 生产管理(Production):工序、工艺路线、生产工单、生产任务、报工反馈、流转卡、安灯、停机记录等核心生产执行 + */ +package cn.iocoder.yudao.module.mes.controller.admin.pro; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/MesProProcessContentController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/MesProProcessContentController.java new file mode 100644 index 000000000..63012317b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/MesProProcessContentController.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.process; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.content.MesProProcessContentRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.content.MesProProcessContentSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessContentDO; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessContentService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 生产工序内容") +@RestController +@RequestMapping("/mes/pro/process-content") +@Validated +public class MesProProcessContentController { + + @Resource + private MesProProcessContentService processContentService; + + @PostMapping("/create") + @Operation(summary = "创建生产工序内容") + @PreAuthorize("@ss.hasPermission('mes:pro-process:update')") + public CommonResult createProcessContent(@Valid @RequestBody MesProProcessContentSaveReqVO createReqVO) { + return success(processContentService.createProcessContent(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新生产工序内容") + @PreAuthorize("@ss.hasPermission('mes:pro-process:update')") + public CommonResult updateProcessContent(@Valid @RequestBody MesProProcessContentSaveReqVO updateReqVO) { + processContentService.updateProcessContent(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产工序内容") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-process:update')") + public CommonResult deleteProcessContent(@RequestParam("id") Long id) { + processContentService.deleteProcessContent(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产工序内容") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-process:query')") + public CommonResult getProcessContent(@RequestParam("id") Long id) { + MesProProcessContentDO content = processContentService.getProcessContent(id); + return success(BeanUtils.toBean(content, MesProProcessContentRespVO.class)); + } + + @GetMapping("/list-by-process") + @Operation(summary = "获得生产工序内容列表(按工序编号)") + @Parameter(name = "processId", description = "工序编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-process:query')") + public CommonResult> getProcessContentListByProcessId(@RequestParam("processId") Long processId) { + List list = processContentService.getProcessContentListByProcessId(processId); + return success(BeanUtils.toBean(list, MesProProcessContentRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/MesProProcessController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/MesProProcessController.java new file mode 100644 index 000000000..7428856ca --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/MesProProcessController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.process; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.process.vo.MesProProcessPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcessRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +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.convertList; + +@Tag(name = "管理后台 - MES 生产工序") +@RestController +@RequestMapping("/mes/pro/process") +@Validated +public class MesProProcessController { + + @Resource + private MesProProcessService processService; + + @PostMapping("/create") + @Operation(summary = "创建生产工序") + @PreAuthorize("@ss.hasPermission('mes:pro-process:create')") + public CommonResult createProcess(@Valid @RequestBody MesProProcessSaveReqVO createReqVO) { + return success(processService.createProcess(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新生产工序") + @PreAuthorize("@ss.hasPermission('mes:pro-process:update')") + public CommonResult updateProcess(@Valid @RequestBody MesProProcessSaveReqVO updateReqVO) { + processService.updateProcess(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产工序") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-process:delete')") + public CommonResult deleteProcess(@RequestParam("id") Long id) { + processService.deleteProcess(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产工序") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-process:query')") + public CommonResult getProcess(@RequestParam("id") Long id) { + MesProProcessDO process = processService.getProcess(id); + return success(BeanUtils.toBean(process, MesProProcessRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得生产工序分页") + @PreAuthorize("@ss.hasPermission('mes:pro-process:query')") + public CommonResult> getProcessPage(@Valid MesProProcessPageReqVO pageReqVO) { + PageResult pageResult = processService.getProcessPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesProProcessRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得生产工序精简列表", description = "只包含被开启的工序,主要用于前端的下拉选项") + public CommonResult> getProcessSimpleList() { + List list = processService.getProcessListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, process -> new MesProProcessRespVO() + .setId(process.getId()).setName(process.getName()).setCode(process.getCode()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出生产工序 Excel") + @PreAuthorize("@ss.hasPermission('mes:pro-process:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportProcessExcel(@Valid MesProProcessPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = processService.getProcessPage(pageReqVO).getList(); + List data = BeanUtils.toBean(list, MesProProcessRespVO.class); + ExcelUtils.write(response, "生产工序.xls", "数据", MesProProcessRespVO.class, data); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessPageReqVO.java new file mode 100644 index 000000000..ff0289f0b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 生产工序分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProProcessPageReqVO extends PageParam { + + @Schema(description = "工序编码", example = "PROCESS001") + private String code; + + @Schema(description = "工序名称", example = "下料工序") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessRespVO.java new file mode 100644 index 000000000..27a241495 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产工序 Response VO") +@Data +public class MesProProcessRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "工序编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PROCESS001") + private String code; + + @Schema(description = "工序名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "下料工序") + private String name; + + @Schema(description = "工艺要求", example = "按照图纸尺寸进行切割") + private String attention; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; + + @Schema(description = "备注", example = "金属板材下料") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessSaveReqVO.java new file mode 100644 index 000000000..2abbd0cc8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/MesProProcessSaveReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 生产工序新增/修改 Request VO") +@Data +public class MesProProcessSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "工序编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PROCESS001") + @NotBlank(message = "工序编码不能为空") + private String code; + + @Schema(description = "工序名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "下料工序") + @NotBlank(message = "工序名称不能为空") + private String name; + + @Schema(description = "工艺要求", example = "按照图纸尺寸进行切割") + private String attention; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "金属板材下料") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentPageReqVO.java new file mode 100644 index 000000000..beb52950d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentPageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.content; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 生产工序内容分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProProcessContentPageReqVO extends PageParam { + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "工序编号不能为空") + private Long processId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentRespVO.java new file mode 100644 index 000000000..5881b66d4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentRespVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.content; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产工序内容 Response VO") +@Data +public class MesProProcessContentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long processId; + + @Schema(description = "顺序编号", example = "1") + private Integer sort; + + @Schema(description = "步骤说明", example = "检查焊接设备是否正常") + private String content; + + @Schema(description = "辅助设备", example = "氩弧焊机") + private String device; + + @Schema(description = "辅助材料", example = "焊丝 ER308") + private String material; + + @Schema(description = "材料文档 URL", example = "https://example.com/doc.pdf") + private String docUrl; + + @Schema(description = "备注", example = "注意安全") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentSaveReqVO.java new file mode 100644 index 000000000..ef51a04bb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/process/vo/content/MesProProcessContentSaveReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.content; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 生产工序内容新增/修改 Request VO") +@Data +public class MesProProcessContentSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工序编号不能为空") + private Long processId; + + @Schema(description = "顺序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "顺序编号不能为空") + private Integer sort; + + @Schema(description = "步骤说明", example = "检查焊接设备是否正常") + private String content; + + @Schema(description = "辅助设备", example = "氩弧焊机") + private String device; + + @Schema(description = "辅助材料", example = "焊丝 ER308") + private String material; + + @Schema(description = "材料文档 URL", example = "https://example.com/doc.pdf") + private String docUrl; + + @Schema(description = "备注", example = "注意安全") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteController.java new file mode 100644 index 000000000..02191d3c8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteController.java @@ -0,0 +1,116 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.route.vo.MesProRoutePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.MesProRouteRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.MesProRouteSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +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.convertList; + +@Tag(name = "管理后台 - MES 工艺路线") +@RestController +@RequestMapping("/mes/pro/route") +@Validated +public class MesProRouteController { + + @Resource + private MesProRouteService routeService; + + @PostMapping("/create") + @Operation(summary = "创建工艺路线") + @PreAuthorize("@ss.hasPermission('mes:pro-route:create')") + public CommonResult createRoute(@Valid @RequestBody MesProRouteSaveReqVO createReqVO) { + return success(routeService.createRoute(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工艺路线") + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult updateRoute(@Valid @RequestBody MesProRouteSaveReqVO updateReqVO) { + routeService.updateRoute(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新工艺路线状态") + @Parameters({ + @Parameter(name = "id", description = "编号", required = true), + @Parameter(name = "status", description = "状态", required = true) + }) + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult updateRouteStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + routeService.updateRouteStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工艺路线") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-route:delete')") + public CommonResult deleteRoute(@RequestParam("id") Long id) { + routeService.deleteRoute(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工艺路线") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult getRoute(@RequestParam("id") Long id) { + MesProRouteDO route = routeService.getRoute(id); + return success(BeanUtils.toBean(route, MesProRouteRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得工艺路线分页") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult> getRoutePage(@Valid MesProRoutePageReqVO pageReqVO) { + PageResult pageResult = routeService.getRoutePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesProRouteRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得工艺路线精简列表", description = "只包含被开启的工艺路线,主要用于前端的下拉选项") + public CommonResult> getRouteSimpleList() { + List list = routeService.getRouteListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, route -> new MesProRouteRespVO() + .setId(route.getId()).setName(route.getName()).setCode(route.getCode()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出工艺路线 Excel") + @PreAuthorize("@ss.hasPermission('mes:pro-route:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportRouteExcel(@Valid MesProRoutePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = routeService.getRoutePage(pageReqVO).getList(); + List data = BeanUtils.toBean(list, MesProRouteRespVO.class); + ExcelUtils.write(response, "工艺路线.xls", "数据", MesProRouteRespVO.class, data); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProcessController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProcessController.java new file mode 100644 index 000000000..d09cad682 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProcessController.java @@ -0,0 +1,135 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProRouteProcessRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProRouteProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 工艺路线工序") +@RestController +@RequestMapping("/mes/pro/route-process") +@Validated +public class MesProRouteProcessController { + + @Resource + private MesProRouteProcessService routeProcessService; + + @Resource + private MesProProcessService processService; + + @PostMapping("/create") + @Operation(summary = "创建工艺路线工序") + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult createRouteProcess(@Valid @RequestBody MesProRouteProcessSaveReqVO createReqVO) { + return success(routeProcessService.createRouteProcess(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工艺路线工序") + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult updateRouteProcess(@Valid @RequestBody MesProRouteProcessSaveReqVO updateReqVO) { + routeProcessService.updateRouteProcess(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工艺路线工序") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult deleteRouteProcess(@RequestParam("id") Long id) { + routeProcessService.deleteRouteProcess(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工艺路线工序") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult getRouteProcess(@RequestParam("id") Long id) { + MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcess(id); + return success(buildRouteProcessRespVO(routeProcess)); + } + + // TODO @芋艿:到底叫 list-by-item 还是 list-by-product? + @GetMapping("/list-by-product") + @Operation(summary = "按产品获得工序列表", description = "根据产品查找关联的工艺路线,返回该路线的工序列表") + @Parameter(name = "productId", description = "产品编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult> getRouteProcessListByProduct(@RequestParam("productId") Long productId) { + List list = routeProcessService.getRouteProcessListByProductId(productId); + return success(buildRouteProcessRespVOList(list)); + } + + @GetMapping("/list-by-route") + @Operation(summary = "按工艺路线获得工序列表") + @Parameter(name = "routeId", description = "工艺路线编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult> getRouteProcessListByRoute(@RequestParam("routeId") Long routeId) { + List list = routeProcessService.getRouteProcessListByRouteId(routeId); + return success(buildRouteProcessRespVOList(list)); + } + + @GetMapping("/get-by-route-and-process") + @Operation(summary = "按工艺路线+工序获得工序配置") + @Parameter(name = "routeId", description = "工艺路线编号", required = true, example = "1") + @Parameter(name = "processId", description = "工序编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult getRouteProcessByRouteAndProcess( + @RequestParam("routeId") Long routeId, + @RequestParam("processId") Long processId) { + MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId); + return success(buildRouteProcessRespVO(routeProcess)); + } + + // ==================== 拼接 VO ==================== + + private List buildRouteProcessRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Set processIds = convertSet(list, MesProRouteProcessDO::getProcessId); + list.forEach(item -> { if (item.getNextProcessId() != null) processIds.add(item.getNextProcessId()); }); + Map processMap = convertMap( + processService.getProcessList(new ArrayList<>(processIds)), MesProProcessDO::getId); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProRouteProcessRespVO.class, vo -> { + MapUtils.findAndThen(processMap, vo.getProcessId(), + process -> vo.setProcessCode(process.getCode()).setProcessName(process.getName())); + MapUtils.findAndThen(processMap, vo.getNextProcessId(), + nextProcess -> vo.setNextProcessName(nextProcess.getName())); + }); + } + + private MesProRouteProcessRespVO buildRouteProcessRespVO(MesProRouteProcessDO routeProcess) { + if (routeProcess == null) { + return null; + } + return buildRouteProcessRespVOList(List.of(routeProcess)).get(0); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProductBomController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProductBomController.java new file mode 100644 index 000000000..6fc55bc2f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProductBomController.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomSaveReqVO; +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.route.MesProRouteProductBomDO; +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.route.MesProRouteProductBomService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +@Tag(name = "管理后台 - MES 工艺路线产品 BOM") +@RestController +@RequestMapping("/mes/pro/route-product-bom") +@Validated +public class MesProRouteProductBomController { + + @Resource + private MesProRouteProductBomService routeProductBomService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建工艺路线产品 BOM") + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult createRouteProductBom(@Valid @RequestBody MesProRouteProductBomSaveReqVO createReqVO) { + return success(routeProductBomService.createRouteProductBom(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工艺路线产品 BOM") + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult updateRouteProductBom(@Valid @RequestBody MesProRouteProductBomSaveReqVO updateReqVO) { + routeProductBomService.updateRouteProductBom(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工艺路线产品 BOM") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult deleteRouteProductBom(@RequestParam("id") Long id) { + routeProductBomService.deleteRouteProductBom(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工艺路线产品 BOM") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult getRouteProductBom(@RequestParam("id") Long id) { + MesProRouteProductBomDO routeProductBom = routeProductBomService.getRouteProductBom(id); + return success(buildRouteProductBomRespVO(routeProductBom)); + } + + @GetMapping("/list") + @Operation(summary = "查询工艺路线产品 BOM 列表") + @Parameters({ + @Parameter(name = "routeId", description = "工艺路线编号", required = true, example = "1"), + @Parameter(name = "processId", description = "工序编号", example = "1"), + @Parameter(name = "productId", description = "产品物料编号", example = "1") + }) + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult> getRouteProductBomList( + @RequestParam("routeId") Long routeId, + @RequestParam(value = "processId", required = false) Long processId, + @RequestParam(value = "productId", required = false) Long productId) { + List list = routeProductBomService.getRouteProductBomList(routeId, processId, productId); + return success(buildRouteProductBomRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRouteProductBomRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesProRouteProductBomDO::getItemId)); + Map unitMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProRouteProductBomRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()) + .setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMap, item.getUnitMeasureId(), + unit -> vo.setUnitName(unit.getName())); + }); + }); + } + + private MesProRouteProductBomRespVO buildRouteProductBomRespVO(MesProRouteProductBomDO routeProductBom) { + if (routeProductBom == null) { + return null; + } + return buildRouteProductBomRespVOList(List.of(routeProductBom)).get(0); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProductController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProductController.java new file mode 100644 index 000000000..59a5e24c3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProductController.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductSaveReqVO; +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.route.MesProRouteProductDO; +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.route.MesProRouteProductService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +@Tag(name = "管理后台 - MES 工艺路线产品") +@RestController +@RequestMapping("/mes/pro/route-product") +@Validated +public class MesProRouteProductController { + + @Resource + private MesProRouteProductService routeProductService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建工艺路线产品") + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult createRouteProduct(@Valid @RequestBody MesProRouteProductSaveReqVO createReqVO) { + return success(routeProductService.createRouteProduct(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工艺路线产品") + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult updateRouteProduct(@Valid @RequestBody MesProRouteProductSaveReqVO updateReqVO) { + routeProductService.updateRouteProduct(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工艺路线产品") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')") + public CommonResult deleteRouteProduct(@RequestParam("id") Long id) { + routeProductService.deleteRouteProduct(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工艺路线产品") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult getRouteProduct(@RequestParam("id") Long id) { + MesProRouteProductDO routeProduct = routeProductService.getRouteProduct(id); + return success(buildRouteProductRespVO(routeProduct)); + } + + @GetMapping("/list-by-route") + @Operation(summary = "按工艺路线获得产品列表") + @Parameter(name = "routeId", description = "工艺路线编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('mes:pro-route:query')") + public CommonResult> getRouteProductListByRoute(@RequestParam("routeId") Long routeId) { + List list = routeProductService.getRouteProductListByRouteId(routeId); + return success(buildRouteProductRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRouteProductRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesProRouteProductDO::getItemId)); + Map unitMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProRouteProductRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()) + .setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMap, item.getUnitMeasureId(), + unit -> vo.setUnitName(unit.getName())); + }); + }); + } + + private MesProRouteProductRespVO buildRouteProductRespVO(MesProRouteProductDO routeProduct) { + if (routeProduct == null) { + return null; + } + return buildRouteProductRespVOList(List.of(routeProduct)).get(0); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRoutePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRoutePageReqVO.java new file mode 100644 index 000000000..2c8a50eda --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRoutePageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 工艺路线分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProRoutePageReqVO extends PageParam { + + @Schema(description = "工艺路线编码", example = "ROUTE001") + private String code; + + @Schema(description = "工艺路线名称", example = "标准路线") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteRespVO.java new file mode 100644 index 000000000..749d4a282 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteRespVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工艺路线 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesProRouteRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "工艺路线编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ROUTE001") + @ExcelProperty("工艺路线编码") + private String code; + + @Schema(description = "工艺路线名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "标准路线") + @ExcelProperty("工艺路线名称") + private String name; + + @Schema(description = "工艺路线说明") + @ExcelProperty("工艺路线说明") + private String description; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteSaveReqVO.java new file mode 100644 index 000000000..cb44f4fc0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteSaveReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Schema(description = "管理后台 - MES 工艺路线新增/修改 Request VO") +@Data +public class MesProRouteSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "工艺路线编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ROUTE001") + @NotBlank(message = "工艺路线编码不能为空") + private String code; + + @Schema(description = "工艺路线名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "标准路线") + @NotBlank(message = "工艺路线名称不能为空") + private String name; + + @Schema(description = "工艺路线说明") + private String description; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/process/MesProRouteProcessRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/process/MesProRouteProcessRespVO.java new file mode 100644 index 000000000..78608e6a7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/process/MesProRouteProcessRespVO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工艺路线工序 Response VO") +@Data +public class MesProRouteProcessRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "工艺路线编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long routeId; + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long processId; + + @Schema(description = "工序编码") + private String processCode; + + @Schema(description = "工序名称") + private String processName; + + @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sort; + + @Schema(description = "下一道工序编号") + private Long nextProcessId; + + @Schema(description = "下一道工序名称") + private String nextProcessName; + + @Schema(description = "与下一道工序关系", example = "0") + private Integer linkType; + + @Schema(description = "准备时间(分钟)", example = "10") + private Integer prepareTime; + + @Schema(description = "等待时间(分钟)", example = "5") + private Integer waitTime; + + @Schema(description = "甘特图显示颜色", example = "#00AEF3") + private String colorCode; + + @Schema(description = "是否关键工序", example = "false") + private Boolean keyFlag; + + @Schema(description = "是否质检工序", example = "false") + private Boolean checkFlag; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/process/MesProRouteProcessSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/process/MesProRouteProcessSaveReqVO.java new file mode 100644 index 000000000..9cde37c7d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/process/MesProRouteProcessSaveReqVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 工艺路线工序新增/修改 Request VO") +@Data +public class MesProRouteProcessSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "工艺路线编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工艺路线编号不能为空") + private Long routeId; + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工序编号不能为空") + private Long processId; + + @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "序号不能为空") + private Integer sort; + + @Schema(description = "与下一道工序关系", example = "0") + private Integer linkType; + + @Schema(description = "准备时间(分钟)", example = "10") + private Integer prepareTime; + + @Schema(description = "等待时间(分钟)", example = "5") + private Integer waitTime; + + @Schema(description = "甘特图显示颜色", example = "#00AEF3") + private String colorCode; + + @Schema(description = "是否关键工序", example = "false") + private Boolean keyFlag; + + @Schema(description = "是否质检工序", example = "false") + private Boolean checkFlag; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/product/MesProRouteProductRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/product/MesProRouteProductRespVO.java new file mode 100644 index 000000000..8df87e934 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/product/MesProRouteProductRespVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工艺路线产品 Response VO") +@Data +public class MesProRouteProductRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "工艺路线编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long routeId; + + @Schema(description = "产品物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "产品物料编码") + private String itemCode; + + @Schema(description = "产品物料名称") + private String itemName; + + @Schema(description = "规格型号") + private String specification; + + @Schema(description = "单位名称") + private String unitName; + + @Schema(description = "生产数量", example = "100") + private Integer quantity; + + @Schema(description = "生产用时", example = "60.00") + private BigDecimal productionTime; + + @Schema(description = "时间单位", example = "MINUTE") + private String timeUnitType; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/product/MesProRouteProductSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/product/MesProRouteProductSaveReqVO.java new file mode 100644 index 000000000..db5ecf124 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/product/MesProRouteProductSaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 工艺路线产品新增/修改 Request VO") +@Data +public class MesProRouteProductSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "工艺路线编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工艺路线编号不能为空") + private Long routeId; + + @Schema(description = "产品物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品物料编号不能为空") + private Long itemId; + + @Schema(description = "生产数量", example = "100") + private Integer quantity; + + @Schema(description = "生产用时", example = "60.00") + private BigDecimal productionTime; + + @Schema(description = "时间单位", example = "MINUTE") + private String timeUnitType; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/productbom/MesProRouteProductBomRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/productbom/MesProRouteProductBomRespVO.java new file mode 100644 index 000000000..a802f12cb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/productbom/MesProRouteProductBomRespVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工艺路线产品 BOM Response VO") +@Data +public class MesProRouteProductBomRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "工艺路线编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long routeId; + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long processId; + + @Schema(description = "产品物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long productId; + + @Schema(description = "BOM 物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "BOM 物料编码") + private String itemCode; + + @Schema(description = "BOM 物料名称") + private String itemName; + + @Schema(description = "规格型号") + private String specification; + + @Schema(description = "单位名称") + private String unitName; + + @Schema(description = "用料比例", example = "1.50") + private BigDecimal quantity; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/productbom/MesProRouteProductBomSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/productbom/MesProRouteProductBomSaveReqVO.java new file mode 100644 index 000000000..7dad3d5ea --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/productbom/MesProRouteProductBomSaveReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 工艺路线产品 BOM 新增/修改 Request VO") +@Data +public class MesProRouteProductBomSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "工艺路线编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工艺路线编号不能为空") + private Long routeId; + + @Schema(description = "工序编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工序编号不能为空") + private Long processId; + + @Schema(description = "产品物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品物料编号不能为空") + private Long productId; + + @Schema(description = "BOM 物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "BOM 物料编号不能为空") + private Long itemId; + + @Schema(description = "用料比例", example = "1.50") + private BigDecimal quantity; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java new file mode 100644 index 000000000..08ded4df2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java @@ -0,0 +1,278 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.task; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.task.vo.GanttDataRespVO; +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; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +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.md.workstation.MesMdWorkstationDO; +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.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +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.md.workstation.MesMdWorkstationService; +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.MesProWorkOrderService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.*; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 生产任务") +@RestController +@RequestMapping("/mes/pro/task") +@Validated +public class MesProTaskController { + + @Resource + private MesProTaskService taskService; + + @Resource + private MesProWorkOrderService workOrderService; + + @Resource + private MesMdWorkstationService workstationService; + + @Resource + private MesProProcessService processService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdClientService clientService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建生产任务") + @PreAuthorize("@ss.hasPermission('mes:pro-task:create')") + public CommonResult createTask(@Valid @RequestBody MesProTaskSaveReqVO createReqVO) { + return success(taskService.createTask(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新生产任务") + @PreAuthorize("@ss.hasPermission('mes:pro-task:update')") + public CommonResult updateTask(@Valid @RequestBody MesProTaskSaveReqVO updateReqVO) { + taskService.updateTask(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产任务") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-task:delete')") + public CommonResult deleteTask(@RequestParam("id") Long id) { + taskService.deleteTask(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产任务") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-task:query')") + public CommonResult getTask(@RequestParam("id") Long id) { + MesProTaskDO task = taskService.getTask(id); + if (task == null) { + return success(null); + } + return success(buildTaskRespVOList(List.of(task)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得生产任务分页") + @PreAuthorize("@ss.hasPermission('mes:pro-task:query')") + public CommonResult> getTaskPage(@Valid MesProTaskPageReqVO pageReqVO) { + PageResult pageResult = taskService.getTaskPage(pageReqVO); + return success(new PageResult<>(buildTaskRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得生产任务精简列表", description = "主要用于前端的下拉选项") + public CommonResult> getTaskSimpleList( + @RequestParam(value = "workOrderId", required = false) Long workOrderId) { + List list = taskService.getTaskListByWorkOrderId(workOrderId); + return success(convertList(list, task -> new MesProTaskRespVO() + .setId(task.getId()).setCode(task.getCode()).setName(task.getName()) + .setWorkOrderId(task.getWorkOrderId()).setWorkstationId(task.getWorkstationId()) + .setRouteId(task.getRouteId()).setProcessId(task.getProcessId()) + .setItemId(task.getItemId()).setStatus(task.getStatus()))); + } + + @GetMapping("/gantt-list") + @Operation(summary = "获得甘特图任务列表", description = "后端组装工单=project + 任务=task 列表") + @PreAuthorize("@ss.hasPermission('mes:pro-task:query')") + public CommonResult> listGanttTaskList(@Valid MesProWorkOrderPageReqVO reqVO) { + // 1.1 查询匹配的工单(不分页) + reqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List workOrders = workOrderService.getWorkOrderPage(reqVO).getList(); + if (CollUtil.isEmpty(workOrders)) { + return success(Collections.emptyList()); + } + // 1.2 批量查询所有工单下的任务,按 workOrderId 分组 + List allTasks = taskService.getTaskListByWorkOrderIds( + convertSet(workOrders, MesProWorkOrderDO::getId)); + Map> taskMap = convertMultiMap(allTasks, MesProTaskDO::getWorkOrderId); + + // 2.1 查询关联数据 + java.util.Set allItemIds = new java.util.HashSet<>(); + allItemIds.addAll(convertSet(workOrders, MesProWorkOrderDO::getProductId)); + allItemIds.addAll(convertSet(allTasks, MesProTaskDO::getItemId)); + Map itemMap = itemService.getItemMap(allItemIds); + Map unitMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map workstationMap = workstationService.getWorkstationMap( + convertSet(allTasks, MesProTaskDO::getWorkstationId)); + Map processMap = processService.getProcessMap( + convertSet(allTasks, MesProTaskDO::getProcessId)); + // 2.2 组装甘特图数据 + List ganttData = new java.util.ArrayList<>(); + for (MesProWorkOrderDO workOrder : workOrders) { + // 2.2.a 工单 -> project 行 + MesMdItemDO item = itemMap.get(workOrder.getProductId()); + String productName = item != null ? item.getName() : ""; + GanttDataRespVO woData = new GanttDataRespVO() + .setId(MesBizTypeConstants.PRO_WORKORDER + "_" + workOrder.getId()) + .setOriginalId(workOrder.getId()) + .setType(MesBizTypeConstants.PRO_WORKORDER) + .setText(buildGanttText(item, workOrder.getQuantity(), unitMap)) + .setProduct(productName) + .setQuantity(workOrder.getQuantity()) + .setDuration(0L) + .setProgress(calcProgress(workOrder.getQuantityProduced(), workOrder.getQuantity())); + if (ObjUtil.notEqual(workOrder.getParentId(), MesProWorkOrderDO.PARENT_ID_NULL)) { + woData.setParent(MesBizTypeConstants.PRO_WORKORDER + "_" + workOrder.getParentId()); + } + ganttData.add(woData); + + // 2.2.b 任务 -> task 行 + List woTasks = taskMap.getOrDefault(workOrder.getId(), Collections.emptyList()); + for (MesProTaskDO task : woTasks) { + MesMdWorkstationDO ws = workstationMap.get(task.getWorkstationId()); + MesProProcessDO proc = processMap.get(task.getProcessId()); + MesMdItemDO taskItem = itemMap.get(task.getItemId()); + GanttDataRespVO tData = new GanttDataRespVO() + .setId(MesBizTypeConstants.PRO_TASK + "_" + task.getId()) + .setOriginalId(task.getId()) + .setType(MesBizTypeConstants.PRO_TASK) + .setText(buildGanttText(taskItem, task.getQuantity(), unitMap)) + .setParent(MesBizTypeConstants.PRO_WORKORDER + "_" + workOrder.getId()) + .setWorkstation(ws != null ? ws.getName() : null) + .setProcess(proc != null ? proc.getName() : null) + .setColor(task.getColorCode()) + .setQuantity(task.getQuantity()) + .setStartDate(task.getStartTime()).setEndDate(task.getEndTime()) + .setDuration(task.getDuration() != null ? task.getDuration().longValue() : null) + .setProgress(calcProgress(task.getProducedQuantity(), task.getQuantity())); + ganttData.add(tData); + } + } + return success(ganttData); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出生产任务 Excel") + @PreAuthorize("@ss.hasPermission('mes:pro-task:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTaskExcel(@Valid MesProTaskPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = taskService.getTaskPage(pageReqVO).getList(); + List voList = buildTaskRespVOList(list); + ExcelUtils.write(response, "生产任务.xls", "数据", MesProTaskRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + private List buildTaskRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询关联数据 + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesProTaskDO::getWorkOrderId)); + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesProTaskDO::getWorkstationId)); + Map processMap = processService.getProcessMap( + new java.util.ArrayList<>(convertSet(list, MesProTaskDO::getProcessId))); + Map itemMap = itemService.getItemMap( + convertSet(list, MesProTaskDO::getItemId)); + Map clientMap = clientService.getClientMap( + convertSet(list, MesProTaskDO::getClientId)); + // 拼接 VO + return convertList(list, task -> { + MesProTaskRespVO vo = BeanUtils.toBean(task, MesProTaskRespVO.class); + findAndThen(workOrderMap, task.getWorkOrderId(), wo -> + vo.setWorkOrderCode(wo.getCode()).setWorkOrderName(wo.getName()).setRequestDate(wo.getRequestDate())); + findAndThen(workstationMap, task.getWorkstationId(), ws -> + vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName())); + findAndThen(processMap, task.getProcessId(), p -> + vo.setProcessName(p.getName())); + findAndThen(itemMap, task.getItemId(), item -> + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification())); + findAndThen(clientMap, task.getClientId(), c -> + vo.setClientName(c.getName())); + return vo; + }); + } + + /** + * 拼接甘特图显示文本,格式:"[产品名][数量][单位]" + */ + private String buildGanttText(MesMdItemDO item, BigDecimal quantity, + Map unitMap) { + String itemName = item != null ? item.getName() : ""; + String quantityStr = quantity != null ? quantity.stripTrailingZeros().toPlainString() : ""; + String unitName = ""; + if (item != null && item.getUnitMeasureId() != null) { + MesMdUnitMeasureDO unit = unitMap.get(item.getUnitMeasureId()); + unitName = unit != null ? unit.getName() : ""; + } + return itemName + quantityStr + unitName; + } + + /** + * 计算进度 = 已生产 / 总量,返回 0~1 + */ + private float calcProgress(BigDecimal produced, BigDecimal total) { + if (total == null || total.compareTo(BigDecimal.ZERO) <= 0 || produced == null) { + return 0f; + } + return produced.divide(total, RoundingMode.HALF_UP).floatValue(); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskIssueController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskIssueController.java new file mode 100644 index 000000000..f0f30d9ed --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskIssueController.java @@ -0,0 +1,124 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.task; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskIssueRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskIssueSaveReqVO; +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.task.MesProTaskIssueDO; +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.task.MesProTaskIssueService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +// TODO @芋艿:【对齐】前端没地方调用,这里只先写后端代码; +@Tag(name = "管理后台 - MES 生产任务投料") +@RestController +@RequestMapping("/mes/pro/task-issue") +@Validated +public class MesProTaskIssueController { + + @Resource + private MesProTaskIssueService taskIssueService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建生产任务投料") + @PreAuthorize("@ss.hasPermission('mes:pro-task-issue:create')") + public CommonResult createTaskIssue(@Valid @RequestBody MesProTaskIssueSaveReqVO createReqVO) { + return success(taskIssueService.createTaskIssue(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新生产任务投料") + @PreAuthorize("@ss.hasPermission('mes:pro-task-issue:update')") + public CommonResult updateTaskIssue(@Valid @RequestBody MesProTaskIssueSaveReqVO updateReqVO) { + taskIssueService.updateTaskIssue(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产任务投料") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-task-issue:delete')") + public CommonResult deleteTaskIssue(@RequestParam("id") Long id) { + taskIssueService.deleteTaskIssue(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产任务投料") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-task-issue:query')") + public CommonResult getTaskIssue(@RequestParam("id") Long id) { + MesProTaskIssueDO taskIssue = taskIssueService.getTaskIssue(id); + if (taskIssue == null) { + return success(null); + } + return success(buildIssueRespVOList(List.of(taskIssue)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得生产任务投料分页") + @PreAuthorize("@ss.hasPermission('mes:pro-task-issue:query')") + public CommonResult> getTaskIssuePage(@Valid MesProTaskIssuePageReqVO pageReqVO) { + PageResult pageResult = taskIssueService.getTaskIssuePage(pageReqVO); + return success(new PageResult<>(buildIssueRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/list-by-task") + @Operation(summary = "根据任务获得投料列表") + @Parameter(name = "taskId", description = "任务编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-task-issue:query')") + public CommonResult> getTaskIssueListByTask(@RequestParam("taskId") Long taskId) { + List list = taskIssueService.getTaskIssueListByTaskId(taskId); + return success(buildIssueRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildIssueRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesProTaskIssueDO::getItemId)); + Map unitMap = unitMeasureService.getUnitMeasureMap( + convertSet(list, MesProTaskIssueDO::getUnitMeasureId)); + // 拼接 VO + return cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList(list, issue -> { + MesProTaskIssueRespVO vo = BeanUtils.toBean(issue, MesProTaskIssueRespVO.class); + findAndThen(itemMap, issue.getItemId(), item -> + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification())); + findAndThen(unitMap, issue.getUnitMeasureId(), unit -> + vo.setUnitMeasureName(unit.getName())); + return vo; + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/GanttDataRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/GanttDataRespVO.java new file mode 100644 index 000000000..173c91a2e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/GanttDataRespVO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 甘特图数据项 VO + */ +@Schema(description = "管理后台 - 甘特图数据项 Response VO") +@Data +@Accessors(chain = true) +public class GanttDataRespVO { + + @Schema(description = "节点 ID(MesBizTypeConstants + '_' + 原始 ID)", example = "301_1") + private String id; + + @Schema(description = "原始业务 ID(工单编号或任务编号,用于编辑回写)") + private Long originalId; + + @Schema(description = "节点类型") + private Integer type; // 使用 MesBizTypeConstants 区分,如 301=工单, 303=任务 + + @Schema(description = "显示文本") + private String text; + + @Schema(description = "父节点 ID") + private String parent; + + @Schema(description = "工作站名称") + private String workstation; + + @Schema(description = "工序名称") + private String process; + + @Schema(description = "产品名称") + private String product; + + @Schema(description = "排产数量") + private BigDecimal quantity; + + @Schema(description = "完成进度(0~1)") + private Float progress; + + @Schema(description = "甘特图颜色") + private String color; + + @Schema(description = "开始时间") + private LocalDateTime startDate; + + @Schema(description = "结束时间") + private LocalDateTime endDate; + + @Schema(description = "生产时长") + private Long duration; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssuePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssuePageReqVO.java new file mode 100644 index 000000000..ce2683b95 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssuePageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 生产任务投料分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProTaskIssuePageReqVO extends PageParam { + + @Schema(description = "生产任务编号", example = "1") + private Long taskId; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "产品物料编号", example = "100") + private Long itemId; + + @Schema(description = "来源单据类型", example = "MATERIAL_ISSUE") + private String sourceDocType; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueRespVO.java new file mode 100644 index 000000000..74e68369f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueRespVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产任务投料 Response VO") +@Data +public class MesProTaskIssueRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "生产任务编号", example = "1") + private Long taskId; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "来源单据编号", example = "1") + private Long sourceDocId; + + @Schema(description = "来源单据编码", example = "DOC-001") + private String sourceDocCode; + + @Schema(description = "来源单据类型", example = "MATERIAL_ISSUE") + private String sourceDocType; + + @Schema(description = "投料批次", example = "BATCH-001") + private String batchCode; + + @Schema(description = "来源单据行编号", example = "1") + private Long sourceLineId; + + @Schema(description = "产品物料编号", example = "100") + private Long itemId; + + @Schema(description = "产品编码", example = "P-001") + private String itemCode; + + @Schema(description = "产品名称", example = "电路板") + private String itemName; + + @Schema(description = "规格型号", example = "100x200mm") + private String itemSpec; + + @Schema(description = "单位编号", example = "1") + private Long unitMeasureId; + + @Schema(description = "单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "总投料数量", example = "100.00") + private BigDecimal issuedQuantity; + + @Schema(description = "当前可用数量", example = "80.00") + private BigDecimal availableQuantity; + + @Schema(description = "当前使用数量", example = "20.00") + private BigDecimal usedQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueSaveReqVO.java new file mode 100644 index 000000000..7c2339a1f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueSaveReqVO.java @@ -0,0 +1,60 @@ +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; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 生产任务投料新增/修改 Request VO") +@Data +public class MesProTaskIssueSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "生产任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "生产任务编号不能为空") + private Long taskId; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "来源单据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "来源单据编号不能为空") + private Long sourceDocId; + + @Schema(description = "来源单据编码", example = "DOC-001") + private String sourceDocCode; + + @Schema(description = "来源单据类型", example = "MATERIAL_ISSUE") + private String sourceDocType; + + @Schema(description = "投料批次", example = "BATCH-001") + private String batchCode; + + @Schema(description = "来源单据行编号", example = "1") + private Long sourceLineId; + + @Schema(description = "产品物料编号", example = "100") + private Long itemId; + + @Schema(description = "单位编号", example = "1") + private Long unitMeasureId; + + @Schema(description = "总投料数量", example = "100.00") + private BigDecimal issuedQuantity; + + @Schema(description = "当前可用数量", example = "80.00") + private BigDecimal availableQuantity; + + @Schema(description = "当前使用数量", example = "20.00") + private BigDecimal usedQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPageReqVO.java new file mode 100644 index 000000000..b38b80148 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPageReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 生产任务分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProTaskPageReqVO extends PageParam { + + @Schema(description = "任务编码", example = "PT202503150001") + private String code; + + @Schema(description = "任务名称", example = "注塑任务") + private String name; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "工艺路线编号", example = "1") + private Long routeId; + + @Schema(description = "工序编号", example = "1") + private Long processId; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "任务状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java new file mode 100644 index 000000000..743ece81b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产任务 Response VO") +@Data +public class MesProTaskRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "任务编码", example = "PT202503150001") + private String code; + + @Schema(description = "任务名称", example = "注塑任务") + private String name; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "工单编码", example = "WO-001") + private String workOrderCode; + + @Schema(description = "工单名称", example = "生产工单-A") + private String workOrderName; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "工作站编码", example = "WS-001") + private String workstationCode; + + @Schema(description = "工作站名称", example = "注塑工作站") + private String workstationName; + + @Schema(description = "工艺路线编号", example = "1") + private Long routeId; + + @Schema(description = "工序编号", example = "1") + private Long processId; + + @Schema(description = "工序名称", example = "注塑") + private String processName; + + @Schema(description = "产品物料编号", example = "100") + private Long itemId; + + @Schema(description = "产品编码", example = "P-001") + private String itemCode; + + @Schema(description = "产品名称", example = "电路板") + private String itemName; + + @Schema(description = "规格型号", example = "100x200mm") + private String itemSpec; + + @Schema(description = "排产数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "已生产数量", example = "50.00") + private BigDecimal producedQuantity; + + @Schema(description = "合格品数量", example = "48.00") + private BigDecimal qualifyQuantity; + + @Schema(description = "不良品数量", example = "2.00") + private BigDecimal unqualifyQuantity; + + @Schema(description = "调整数量", example = "0") + private BigDecimal changedQuantity; + + @Schema(description = "客户编号", example = "300") + private Long clientId; + + @Schema(description = "客户名称", example = "客户A") + private String clientName; + + @Schema(description = "开始生产时间") + private LocalDateTime startTime; + + @Schema(description = "生产时长(工作日)", example = "3") + private Integer duration; + + @Schema(description = "结束生产时间") + private LocalDateTime endTime; + + @Schema(description = "甘特图显示颜色", example = "#00AEF3") + private String colorCode; + + @Schema(description = "需求日期") + private LocalDateTime requestDate; + + @Schema(description = "完成日期") + private LocalDateTime finishDate; + + @Schema(description = "取消日期") + private LocalDateTime cancelDate; + + @Schema(description = "任务状态", example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskSaveReqVO.java new file mode 100644 index 000000000..db9f5e2e3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskSaveReqVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产任务新增/修改 Request VO") +@Data +public class MesProTaskSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; // 编辑时,可不传递 + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; // 编辑时,可不传递 + + @Schema(description = "工艺路线编号", example = "1") + private Long routeId; // 编辑时,可不传递 + + @Schema(description = "工序编号", example = "1") + private Long processId; // 编辑时,可不传递 + + @Schema(description = "产品物料编号", example = "100") + private Long itemId; // 编辑时,可不传递 + + @Schema(description = "排产数量", example = "100.00") + @DecimalMin(value = "0", inclusive = false, message = "排产数量必须大于 0") + private BigDecimal quantity; // 编辑时,可不传递 + + @Schema(description = "开始生产时间") + private LocalDateTime startTime; + + @Schema(description = "生产时长(工作日)", example = "3") + @Min(value = 1, message = "生产时长必须大于 0") + private Integer duration; + + @Schema(description = "结束生产时间") + private LocalDateTime endTime; + + @Schema(description = "甘特图显示颜色", example = "#00AEF3") + private String colorCode; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderBomController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderBomController.java new file mode 100644 index 000000000..464d54d98 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderBomController.java @@ -0,0 +1,209 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderItemRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductBomService; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderBomService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.math.BigDecimal; +import java.util.*; +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 生产工单 BOM") +@RestController +@RequestMapping("/mes/pro/work-order-bom") +@Validated +public class MesProWorkOrderBomController { + + @Resource + private MesProWorkOrderBomService workOrderBomService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesMdItemTypeService itemTypeService; + + @Resource + private MesMdProductBomService productBomService; + + @PostMapping("/create") + @Operation(summary = "创建工单 BOM") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:update')") + public CommonResult createWorkOrderBom(@Valid @RequestBody MesProWorkOrderBomSaveReqVO createReqVO) { + return success(workOrderBomService.createWorkOrderBom(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工单 BOM") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:update')") + public CommonResult updateWorkOrderBom(@Valid @RequestBody MesProWorkOrderBomSaveReqVO updateReqVO) { + workOrderBomService.updateWorkOrderBom(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工单 BOM") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:update')") + public CommonResult deleteWorkOrderBom(@RequestParam("id") Long id) { + workOrderBomService.deleteWorkOrderBom(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工单 BOM") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')") + public CommonResult getWorkOrderBom(@RequestParam("id") Long id) { + MesProWorkOrderBomDO workOrderBom = workOrderBomService.getWorkOrderBom(id); + if (workOrderBom == null) { + return success(null); + } + return success(buildWorkOrderBomRespVOList(List.of(workOrderBom)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得工单 BOM 分页") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')") + public CommonResult> getWorkOrderBomPage(@Valid MesProWorkOrderBomPageReqVO pageReqVO) { + PageResult pageResult = workOrderBomService.getWorkOrderBomPage(pageReqVO); + return success(new PageResult<>(buildWorkOrderBomRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/item-list-by-work-order-id") + @Operation(summary = "获得工单物料需求列表") + @Parameter(name = "workOrderId", description = "工单编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')") + public CommonResult> getWorkOrderBomItemListByWorkOrderId( + @RequestParam("workOrderId") Long workOrderId) { + // 1. 获取工单 BOM 行 + List bomList = workOrderBomService.getWorkOrderBomListByWorkOrderId(workOrderId); + if (CollUtil.isEmpty(bomList)) { + return success(Collections.emptyList()); + } + + // 2. 逐层展开,得到叶子物料 itemId → quantity + Map leafItems = buildWorkOrderItems(bomList); + if (CollUtil.isEmpty(leafItems)) { + return success(Collections.emptyList()); + } + + // 3. 拼接 VO 字段 + Map itemMap = itemService.getItemMap(leafItems.keySet()); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + List result = new ArrayList<>(leafItems.size()); + for (Map.Entry entry : leafItems.entrySet()) { + MesMdItemDO item = itemMap.get(entry.getKey()); + if (item == null) { + continue; + } + MesProWorkOrderItemRespVO vo = new MesProWorkOrderItemRespVO() + .setItemId(item.getId()).setQuantity(entry.getValue()) + .setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + result.add(vo); + } + return success(result); + } + + // ==================== 拼接 VO ==================== + + private List buildWorkOrderBomRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesProWorkOrderBomDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map itemTypeMap = itemTypeService.getItemTypeMap( + convertSet(itemMap.values(), MesMdItemDO::getItemTypeId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProWorkOrderBomRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemName(item.getName()).setItemCode(item.getCode()) + .setItemSpec(item.getSpecification()); + MapUtils.findAndThen(itemTypeMap, item.getItemTypeId(), + itemType -> vo.setItemOrProduct(itemType.getItemOrProduct())); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + + // ==================== 物料需求逐层展开 ==================== + + /** + * 逐层 IN 查询展开工单 BOM 到叶子物料,合并同物料的需求数量 + * + * @param bomList 工单 BOM 列表 + * @return 叶子物料 Map:itemId → 合并后的需求数量 + */ + private Map buildWorkOrderItems(List bomList) { + // 1. 初始化:收集第一层物料 ID 和对应数量 + Map currentLayer = new LinkedHashMap<>(); + for (MesProWorkOrderBomDO bom : bomList) { + currentLayer.merge(bom.getItemId(), bom.getQuantity(), BigDecimal::add); + } + + // 2. 逐层 IN 查询展开 BOM + Map leafItems = new LinkedHashMap<>(); + for (int i = 0; i < Byte.MAX_VALUE && CollUtil.isNotEmpty(currentLayer); i++) { + // 2.1 批量查询当前层所有物料的子 BOM + List subBomList = productBomService.getProductBomListByItemIds(currentLayer.keySet()); + // 2.2 按 itemId 分组 + Map> subBomMap = convertMultiMap(subBomList, MesMdProductBomDO::getItemId); + // 2.3 区分叶子节点和非叶子节点 + Map nextLayer = new LinkedHashMap<>(); + for (Map.Entry entry : currentLayer.entrySet()) { + Long itemId = entry.getKey(); + BigDecimal quantity = entry.getValue(); + List children = subBomMap.get(itemId); + // 情况一:叶子节点,累加到结果 + if (CollUtil.isEmpty(children)) { + leafItems.merge(itemId, quantity, BigDecimal::add); + continue; + } + // 情况二:非叶子,子物料进入下一层 + for (MesMdProductBomDO child : children) { + nextLayer.merge(child.getBomItemId(), quantity.multiply(child.getQuantity()), BigDecimal::add); + } + } + currentLayer = nextLayer; + } + return leafItems; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java new file mode 100644 index 000000000..7d7b6782a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java @@ -0,0 +1,180 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.MesProWorkOrderRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +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.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +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.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +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.convertSet; + +@Tag(name = "管理后台 - MES 生产工单") +@RestController +@RequestMapping("/mes/pro/work-order") +@Validated +public class MesProWorkOrderController { + + @Resource + private MesProWorkOrderService workOrderService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdClientService clientService; + + @Resource + private MesMdVendorService vendorService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建生产工单") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:create')") + public CommonResult createWorkOrder(@Valid @RequestBody MesProWorkOrderSaveReqVO createReqVO) { + return success(workOrderService.createWorkOrder(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新生产工单") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:update')") + public CommonResult updateWorkOrder(@Valid @RequestBody MesProWorkOrderSaveReqVO updateReqVO) { + workOrderService.updateWorkOrder(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产工单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:delete')") + public CommonResult deleteWorkOrder(@RequestParam("id") Long id) { + workOrderService.deleteWorkOrder(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产工单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')") + public CommonResult getWorkOrder(@RequestParam("id") Long id) { + MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(id); + if (workOrder == null) { + return success(null); + } + return success(buildWorkOrderRespVOList(List.of(workOrder)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得生产工单分页") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:query')") + public CommonResult> getWorkOrderPage(@Valid MesProWorkOrderPageReqVO pageReqVO) { + PageResult pageResult = workOrderService.getWorkOrderPage(pageReqVO); + return success(new PageResult<>(buildWorkOrderRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出生产工单 Excel") + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportWorkOrderExcel(@Valid MesProWorkOrderPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = workOrderService.getWorkOrderPage(pageReqVO).getList(); + List voList = buildWorkOrderRespVOList(list); + ExcelUtils.write(response, "生产工单.xls", "数据", MesProWorkOrderRespVO.class, voList); + } + + @PutMapping("/confirm") + @Operation(summary = "确认工单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:update')") + public CommonResult confirmWorkOrder(@RequestParam("id") Long id) { + workOrderService.confirmWorkOrder(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成工单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:update')") + public CommonResult finishWorkOrder(@RequestParam("id") Long id) { + workOrderService.finishWorkOrder(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消工单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-work-order:update')") + public CommonResult cancelWorkOrder(@RequestParam("id") Long id) { + workOrderService.cancelWorkOrder(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildWorkOrderRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesProWorkOrderDO::getProductId)); + Map clientMap = clientService.getClientMap( + convertSet(list, MesProWorkOrderDO::getClientId)); + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesProWorkOrderDO::getVendorId)); + // 单位从产品关联的 item 获得 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map parentMap = workOrderService.getWorkOrderMap( + convertSet(list, MesProWorkOrderDO::getParentId)); + // 2. 拼接 VO(单位名称从产品关联的 item 获得) + return BeanUtils.toBean(list, MesProWorkOrderRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getProductId(), item -> { + vo.setProductName(item.getName()).setProductCode(item.getCode()) + .setProductSpec(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(clientMap, vo.getClientId(), + client -> vo.setClientName(client.getName()).setClientCode(client.getCode())); + MapUtils.findAndThen(vendorMap, vo.getVendorId(), + vendor -> vo.setVendorName(vendor.getName()).setVendorCode(vendor.getCode())); + MapUtils.findAndThen(parentMap, vo.getParentId(), + parent -> vo.setParentCode(parent.getCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderItemRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderItemRespVO.java new file mode 100644 index 000000000..efd077f79 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderItemRespVO.java @@ -0,0 +1,30 @@ +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 工单物料需求 Response VO") +@Data +public class MesProWorkOrderItemRespVO { + + @Schema(description = "物料编号", example = "100") + private Long itemId; + + @Schema(description = "物料编码", example = "M-001") + private String itemCode; + + @Schema(description = "物料名称", example = "电阻 10K") + private String itemName; + + @Schema(description = "规格型号", example = "0603") + private String itemSpec; + + @Schema(description = "单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "需求数量", example = "1000.00") + private BigDecimal quantity; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java new file mode 100644 index 000000000..357fc314f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 生产工单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProWorkOrderPageReqVO extends PageParam { + + @Schema(description = "工单编码", example = "WO-001") + private String code; + + @Schema(description = "工单名称", example = "生产工单-A") + private String name; + + @Schema(description = "工单类型", example = "1") + private Integer type; + + @Schema(description = "来源单据编号", example = "SO-001") + private String orderSourceCode; + + @Schema(description = "产品编号", example = "100") + private Long productId; + + @Schema(description = "客户编号", example = "300") + private Long clientId; + + @Schema(description = "需求日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] requestDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java new file mode 100644 index 000000000..a42d36b33 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java @@ -0,0 +1,137 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产工单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesProWorkOrderRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "工单编码", example = "WO-001") + @ExcelProperty("工单编码") + private String code; + + @Schema(description = "工单名称", example = "生产工单-A") + @ExcelProperty("工单名称") + private String name; + + @Schema(description = "工单类型", example = "1") + @ExcelProperty(value = "工单类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_PRO_WORK_ORDER_TYPE) + private Integer type; + + @Schema(description = "来源类型", example = "1") + @ExcelProperty(value = "来源类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_PRO_WORK_ORDER_SOURCE_TYPE) + private Integer orderSourceType; + + @Schema(description = "来源单据编号", example = "SO-001") + @ExcelProperty("来源单据编号") + private String orderSourceCode; + + @Schema(description = "产品编号", example = "100") + private Long productId; + + @Schema(description = "产品名称", example = "电路板 A") + @ExcelProperty("产品名称") + private String productName; + + @Schema(description = "产品编码", example = "P-001") + @ExcelProperty("产品编码") + private String productCode; + + @Schema(description = "规格型号", example = "100x200mm") + @ExcelProperty("规格型号") + private String productSpec; + + @Schema(description = "单位名称", example = "个") + @ExcelProperty("单位") + private String unitMeasureName; + + @Schema(description = "生产数量", example = "100.00") + @ExcelProperty("生产数量") + private BigDecimal quantity; + + @Schema(description = "已生产数量", example = "50.00") + @ExcelProperty("已生产数量") + private BigDecimal quantityProduced; + + @Schema(description = "调整数量", example = "0") + @ExcelProperty("调整数量") + private BigDecimal quantityChanged; + + @Schema(description = "已排产数量", example = "80.00") + @ExcelProperty("已排产数量") + private BigDecimal quantityScheduled; + + @Schema(description = "客户编号", example = "300") + private Long clientId; + + @Schema(description = "客户编码", example = "C-001") + @ExcelProperty("客户编码") + private String clientCode; + + @Schema(description = "客户名称", example = "客户 A") + @ExcelProperty("客户名称") + private String clientName; + + @Schema(description = "供应商编号", example = "400") + private Long vendorId; + + @Schema(description = "供应商编码", example = "V-001") + @ExcelProperty("供应商编码") + private String vendorCode; + + @Schema(description = "供应商名称", example = "供应商 A") + @ExcelProperty("供应商名称") + private String vendorName; + + @Schema(description = "批次号", example = "BATCH-001") + @ExcelProperty("批次号") + private String batchCode; + + @Schema(description = "需求日期") + @ExcelProperty("需求日期") + private LocalDateTime requestDate; + + @Schema(description = "父工单编号", example = "0") + private Long parentId; + + @Schema(description = "父工单编码", example = "WO-001") + private String parentCode; + + @Schema(description = "完成时间") + @ExcelProperty("完成时间") + private LocalDateTime finishDate; + + @Schema(description = "取消时间") + @ExcelProperty("取消时间") + private LocalDateTime cancelDate; + + @Schema(description = "工单状态", example = "0") + @ExcelProperty(value = "工单状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_PRO_WORK_ORDER_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderSaveReqVO.java new file mode 100644 index 000000000..b8527bc5f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderSaveReqVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产工单新增/修改 Request VO") +@Data +public class MesProWorkOrderSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "工单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WO-001") + @NotEmpty(message = "工单编码不能为空") + private String code; + + @Schema(description = "工单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "生产工单-A") + @NotEmpty(message = "工单名称不能为空") + private String name; + + @Schema(description = "工单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "工单类型不能为空") + private Integer type; + + @Schema(description = "来源类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "来源类型不能为空") + private Integer orderSourceType; + + @Schema(description = "来源单据编号", example = "SO-001") + private String orderSourceCode; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "产品不能为空") + private Long productId; + + @Schema(description = "生产数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "生产数量不能为空") + private BigDecimal quantity; + + @Schema(description = "已生产数量", example = "0") + private BigDecimal quantityProduced; + + @Schema(description = "调整数量", example = "0") + private BigDecimal quantityChanged; + + @Schema(description = "已排产数量", example = "0") + private BigDecimal quantityScheduled; + + @Schema(description = "客户编号", example = "300") + private Long clientId; + + @Schema(description = "供应商编号", example = "400") + private Long vendorId; + + @Schema(description = "批次号", example = "BATCH-001") + private String batchCode; + + @Schema(description = "需求日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "需求日期不能为空") + private LocalDateTime requestDate; + + @Schema(description = "父工单编号", example = "0") + private Long parentId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomPageReqVO.java new file mode 100644 index 000000000..40fa64974 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomPageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 生产工单 BOM 分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProWorkOrderBomPageReqVO extends PageParam { + + @Schema(description = "生产工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "生产工单编号不能为空") + private Long workOrderId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java new file mode 100644 index 000000000..ca4e31eeb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产工单 BOM Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesProWorkOrderBomRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "生产工单编号", example = "100") + private Long workOrderId; + + @Schema(description = "BOM 物料编号", example = "200") + private Long itemId; + + @Schema(description = "物料名称", example = "电阻 R1") + @ExcelProperty("物料名称") + private String itemName; + + @Schema(description = "物料编码", example = "M-001") + @ExcelProperty("物料编码") + private String itemCode; + + @Schema(description = "规格型号", example = "10K 0603") + @ExcelProperty("规格型号") + private String itemSpec; + + @Schema(description = "单位编号", example = "300") + private Long unitMeasureId; + + @Schema(description = "单位名称", example = "个") + @ExcelProperty("单位") + private String unitMeasureName; + + @Schema(description = "预计使用量", example = "10.00") + @ExcelProperty("预计使用量") + private BigDecimal quantity; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "物料产品标识", example = "PRODUCT") + private String itemOrProduct; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomSaveReqVO.java new file mode 100644 index 000000000..4194be26b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomSaveReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 生产工单 BOM 新增/修改 Request VO") +@Data +public class MesProWorkOrderBomSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "生产工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "生产工单编号不能为空") + private Long workOrderId; + + @Schema(description = "BOM 物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + @NotNull(message = "BOM 物料不能为空") + private Long itemId; + + @Schema(description = "预计使用量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.00") + @NotNull(message = "预计使用量不能为空") + private BigDecimal quantity; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/MesProWorkRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/MesProWorkRecordController.java new file mode 100644 index 000000000..5a594103f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/MesProWorkRecordController.java @@ -0,0 +1,153 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.workrecord.vo.MesProWorkRecordLogPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordLogDO; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.workrecord.MesProWorkRecordService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - MES 工作记录") +@RestController +@RequestMapping("/mes/pro/workrecord") +@Validated +public class MesProWorkRecordController { + + @Resource + private MesProWorkRecordService workRecordService; + @Resource + private MesMdWorkstationService workstationService; + + @Resource + private AdminUserApi adminUserApi; + + @GetMapping("/log/page") + @Operation(summary = "获得工作记录流水分页") + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:query')") + public CommonResult> getWorkRecordLogPage( + @Valid MesProWorkRecordLogPageReqVO pageReqVO) { + PageResult pageResult = workRecordService.getWorkRecordLogPage(pageReqVO); + return success(new PageResult<>(buildWorkRecordLogRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/log/get") + @Operation(summary = "获得工作记录流水") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:query')") + public CommonResult getWorkRecordLog(@RequestParam("id") Long id) { + MesProWorkRecordLogDO log = workRecordService.getWorkRecordLog(id); + return success(buildWorkRecordLogRespVO(log)); + } + + @GetMapping("/log/export-excel") + @Operation(summary = "导出工作记录 Excel") + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportWorkRecordLogExcel(@Valid MesProWorkRecordLogPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = workRecordService.getWorkRecordLogPage(pageReqVO).getList(); + List voList = buildWorkRecordLogRespVOList(list); + ExcelUtils.write(response, "工作记录.xls", "数据", MesProWorkRecordLogRespVO.class, voList); + } + + @PutMapping("/clock-in") + @Operation(summary = "上线(绑定工作站)") + @Parameter(name = "workstationId", description = "工作站编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:clock')") + public CommonResult clockInWorkRecord(@RequestParam("workstationId") Long workstationId) { + return success(workRecordService.clockInWorkRecord(getLoginUserId(), workstationId)); + } + + @PutMapping("/clock-out") + @Operation(summary = "下线(解绑工作站)") + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:clock')") + public CommonResult clockOutWorkRecord() { + return success(workRecordService.clockOutWorkRecord(getLoginUserId())); + } + + @GetMapping("/get-my") + @Operation(summary = "获取当前用户绑定的工作站状态") + @PreAuthorize("@ss.hasPermission('mes:pro-workrecord:query')") + public CommonResult getMyWorkRecord() { + MesProWorkRecordDO record = workRecordService.getWorkRecord(getLoginUserId()); + return success(buildWorkRecordRespVO(record)); + } + + // ==================== 拼接 VO ==================== + + private MesProWorkRecordLogRespVO buildWorkRecordLogRespVO(MesProWorkRecordLogDO log) { + if (log == null) { + return null; + } + return buildWorkRecordLogRespVOList(Collections.singletonList(log)).get(0); + } + + private List buildWorkRecordLogRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 查询相关数据 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesProWorkRecordLogDO::getUserId)); + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesProWorkRecordLogDO::getWorkstationId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesProWorkRecordLogRespVO.class, vo -> { + findAndThen(userMap, vo.getUserId(), user -> + vo.setUserNickname(user.getNickname())); + findAndThen(workstationMap, vo.getWorkstationId(), ws -> + vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName())); + }); + } + + private MesProWorkRecordRespVO buildWorkRecordRespVO(MesProWorkRecordDO record) { + if (record == null) { + return null; + } + MesProWorkRecordRespVO vo = BeanUtils.toBean(record, MesProWorkRecordRespVO.class); + // 拼接工作站信息 + MesMdWorkstationDO ws = workstationService.getWorkstation(record.getWorkstationId()); + if (ws != null) { + vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName()); + } + // 拼接用户信息 + AdminUserRespDTO user = adminUserApi.getUser(record.getUserId()).getCheckedData(); + if (user != null) { + vo.setUserNickname(user.getNickname()); + } + return vo; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogPageReqVO.java new file mode 100644 index 000000000..10d69eae2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 上下工记录流水分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesProWorkRecordLogPageReqVO extends PageParam { + + @Schema(description = "用户编号", example = "1") + private Long userId; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "操作类型(1=上工 2=下工)", example = "1") + private Integer type; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogRespVO.java new file mode 100644 index 000000000..31777906d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogRespVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 上下工记录流水 Response VO") +@Data +@Accessors(chain = true) +@ExcelIgnoreUnannotated +public class MesProWorkRecordLogRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "用户编号", example = "1") + private Long userId; + + @Schema(description = "用户昵称", example = "张三") + @ExcelProperty("用户昵称") + private String userNickname; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "工作站编码", example = "WS-001") + @ExcelProperty("工作站编码") + private String workstationCode; + + @Schema(description = "工作站名称", example = "注塑工作站") + @ExcelProperty("工作站名称") + private String workstationName; + + @Schema(description = "操作类型(1=上工 2=下工)", example = "1") + @ExcelProperty(value = "操作类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_PRO_WORK_RECORD_TYPE) + private Integer type; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordRespVO.java new file mode 100644 index 000000000..5d4444713 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordRespVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 当前用户工作站绑定状态 Response VO") +@Data +@Accessors(chain = true) +public class MesProWorkRecordRespVO { + + @Schema(description = "用户编号", example = "1") + private Long userId; + + @Schema(description = "用户昵称", example = "张三") + private String userNickname; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "工作站编码", example = "WS-001") + private String workstationCode; + + @Schema(description = "工作站名称", example = "注塑工作站") + private String workstationName; + + @Schema(description = "当前状态", example = "1") + private Integer type; + + @Schema(description = "上工时间") + private LocalDateTime clockInTime; + + @Schema(description = "下工时间") + private LocalDateTime clockOutTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/MesQcDefectController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/MesQcDefectController.java new file mode 100644 index 000000000..9c76651f0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/MesQcDefectController.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.defect; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.qc.defect.vo.MesQcDefectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectDO; +import cn.iocoder.yudao.module.mes.service.qc.defect.MesQcDefectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 缺陷类型") +@RestController +@RequestMapping("/mes/qc/defect") +@Validated +public class MesQcDefectController { + + @Resource + private MesQcDefectService defectService; + + @PostMapping("/create") + @Operation(summary = "创建缺陷类型") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:create')") + public CommonResult createDefect(@Valid @RequestBody MesQcDefectSaveReqVO createReqVO) { + return success(defectService.createDefect(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新缺陷类型") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:update')") + public CommonResult updateDefect(@Valid @RequestBody MesQcDefectSaveReqVO updateReqVO) { + defectService.updateDefect(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除缺陷类型") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-defect:delete')") + public CommonResult deleteDefect(@RequestParam("id") Long id) { + defectService.deleteDefect(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得缺陷类型") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:query')") + public CommonResult getDefect(@RequestParam("id") Long id) { + MesQcDefectDO defect = defectService.getDefect(id); + return success(BeanUtils.toBean(defect, MesQcDefectRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得缺陷类型分页") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:query')") + public CommonResult> getDefectPage(@Valid MesQcDefectPageReqVO pageReqVO) { + PageResult pageResult = defectService.getDefectPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesQcDefectRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得缺陷类型精简列表", description = "主要用于前端的下拉选项") + public CommonResult> getDefectSimpleList() { + List list = defectService.getDefectList(); + return success(BeanUtils.toBean(list, MesQcDefectRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出缺陷类型 Excel") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportDefectExcel(@Valid MesQcDefectPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = defectService.getDefectPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "缺陷类型.xls", "数据", MesQcDefectRespVO.class, + BeanUtils.toBean(list, MesQcDefectRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectPageReqVO.java new file mode 100644 index 000000000..7f2638cd9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 缺陷类型分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcDefectPageReqVO extends PageParam { + + @Schema(description = "缺陷编码", example = "DF001") + private String code; + + @Schema(description = "缺陷描述", example = "外观缺陷") + private String name; + + @Schema(description = "检测项类型", example = "APPEARANCE") + private String type; + + @Schema(description = "缺陷等级", example = "1") + private Integer level; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java new file mode 100644 index 000000000..37cb917a1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 缺陷类型 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcDefectRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "缺陷编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "DF001") + @ExcelProperty("缺陷编码") + private String code; + + @Schema(description = "缺陷描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "外观缺陷") + @ExcelProperty("缺陷描述") + private String name; + + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "APPEARANCE") + @ExcelProperty(value = "检测项类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DEFECT_TYPE) + private String type; + + @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "缺陷等级", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_DEFECT_LEVEL) + private Integer level; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectSaveReqVO.java new file mode 100644 index 000000000..7fb00a5e2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectSaveReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 缺陷类型新增/修改 Request VO") +@Data +public class MesQcDefectSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "缺陷编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "DF001") + @NotEmpty(message = "缺陷编码不能为空") + private String code; + + @Schema(description = "缺陷描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "外观缺陷") + @NotEmpty(message = "缺陷描述不能为空") + private String name; + + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "APPEARANCE") + @NotEmpty(message = "检测项类型不能为空") + private String type; + + @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "缺陷等级不能为空") + @InEnum(MesQcDefectLevelEnum.class) + private Integer level; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/MesQcDefectRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/MesQcDefectRecordController.java new file mode 100644 index 000000000..0c60a5c39 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/MesQcDefectRecordController.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo.MesQcDefectRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo.MesQcDefectRecordRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo.MesQcDefectRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 质检缺陷记录") +@RestController +@RequestMapping("/mes/qc/defect-record") +@Validated +public class MesQcDefectRecordController { + + @Resource + private MesQcDefectRecordService defectRecordService; + + @PostMapping("/create") + @Operation(summary = "创建质检缺陷记录") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:create')") + public CommonResult createDefectRecord(@Valid @RequestBody MesQcDefectRecordSaveReqVO createReqVO) { + return success(defectRecordService.createDefectRecord(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新质检缺陷记录") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:update')") + public CommonResult updateDefectRecord(@Valid @RequestBody MesQcDefectRecordSaveReqVO updateReqVO) { + defectRecordService.updateDefectRecord(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除质检缺陷记录") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-defect:update')") + public CommonResult deleteDefectRecord(@RequestParam("id") Long id) { + defectRecordService.deleteDefectRecord(id); + return success(true); + } + + @GetMapping("/page") + @Operation(summary = "获得质检缺陷记录分页") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:query')") + public CommonResult> getDefectRecordPage(@Valid MesQcDefectRecordPageReqVO pageReqVO) { + PageResult pageResult = defectRecordService.getDefectRecordPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesQcDefectRecordRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordPageReqVO.java new file mode 100644 index 000000000..00806e25d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 质检缺陷记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcDefectRecordPageReqVO extends PageParam { + + @Schema(description = "检验类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检验类型不能为空") + @InEnum(MesQcTypeEnum.class) + private Integer qcType; + + @Schema(description = "检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "检验单 ID 不能为空") + private Long qcId; + + @Schema(description = "检验行 ID", example = "200") + private Long lineId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordRespVO.java new file mode 100644 index 000000000..82643be12 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordRespVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 质检缺陷记录 Response VO") +@Data +public class MesQcDefectRecordRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "检验类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer qcType; + + @Schema(description = "检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long qcId; + + @Schema(description = "检验行 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + private Long lineId; + + @Schema(description = "缺陷描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "表面划伤") + private String name; + + @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer level; + + @Schema(description = "缺陷数量", example = "1") + private Integer quantity; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordSaveReqVO.java new file mode 100644 index 000000000..2856c8fb6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/vo/MesQcDefectRecordSaveReqVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 质检缺陷记录新增/修改 Request VO") +@Data +public class MesQcDefectRecordSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "检验类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检验类型不能为空") + @InEnum(MesQcTypeEnum.class) + private Integer qcType; + + @Schema(description = "检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "检验单 ID 不能为空") + private Long qcId; + + @Schema(description = "检验行 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") + @NotNull(message = "检验行 ID 不能为空") + private Long lineId; + + @Schema(description = "缺陷描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "表面划伤") + @NotEmpty(message = "缺陷描述不能为空") + private String name; + + @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "缺陷等级不能为空") + @InEnum(MesQcDefectLevelEnum.class) + private Integer level; + + @Schema(description = "缺陷数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "缺陷数量不能为空") + private Integer quantity; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/MesQcIndicatorController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/MesQcIndicatorController.java new file mode 100644 index 000000000..e225452c1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/MesQcIndicatorController.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicator; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.qc.indicator.vo.MesQcIndicatorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo.MesQcIndicatorRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo.MesQcIndicatorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 质检指标") +@RestController +@RequestMapping("/mes/qc/indicator") +@Validated +public class MesQcIndicatorController { + + @Resource + private MesQcIndicatorService indicatorService; + + @PostMapping("/create") + @Operation(summary = "创建质检指标") + @PreAuthorize("@ss.hasPermission('mes:qc-indicator:create')") + public CommonResult createIndicator(@Valid @RequestBody MesQcIndicatorSaveReqVO createReqVO) { + return success(indicatorService.createIndicator(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新质检指标") + @PreAuthorize("@ss.hasPermission('mes:qc-indicator:update')") + public CommonResult updateIndicator(@Valid @RequestBody MesQcIndicatorSaveReqVO updateReqVO) { + indicatorService.updateIndicator(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除质检指标") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-indicator:delete')") + public CommonResult deleteIndicator(@RequestParam("id") Long id) { + indicatorService.deleteIndicator(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得质检指标") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-indicator:query')") + public CommonResult getIndicator(@RequestParam("id") Long id) { + MesQcIndicatorDO indicator = indicatorService.getIndicator(id); + return success(BeanUtils.toBean(indicator, MesQcIndicatorRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得质检指标分页") + @PreAuthorize("@ss.hasPermission('mes:qc-indicator:query')") + public CommonResult> getIndicatorPage(@Valid MesQcIndicatorPageReqVO pageReqVO) { + PageResult pageResult = indicatorService.getIndicatorPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesQcIndicatorRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得质检指标精简列表", description = "主要用于前端的下拉选项") + public CommonResult> getIndicatorSimpleList() { + List list = indicatorService.getIndicatorList(); + return success(BeanUtils.toBean(list, MesQcIndicatorRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出质检指标 Excel") + @PreAuthorize("@ss.hasPermission('mes:qc-indicator:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportIndicatorExcel(@Valid MesQcIndicatorPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = indicatorService.getIndicatorPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "质检指标.xls", "数据", MesQcIndicatorRespVO.class, + BeanUtils.toBean(list, MesQcIndicatorRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorPageReqVO.java new file mode 100644 index 000000000..773814e28 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 质检指标分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcIndicatorPageReqVO extends PageParam { + + @Schema(description = "检测项编码", example = "QI001") + private String code; + + @Schema(description = "检测项名称", example = "长度") + private String name; + + @Schema(description = "检测项类型", example = "SIZE") + private String type; + + @Schema(description = "结果值类型", example = "1") + private Integer resultType; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java new file mode 100644 index 000000000..f4b7f9c34 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 质检指标 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcIndicatorRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "检测项编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "QI001") + @ExcelProperty("检测项编码") + private String code; + + @Schema(description = "检测项名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "长度") + @ExcelProperty("检测项名称") + private String name; + + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "SIZE") + @ExcelProperty(value = "检测项类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_INDICATOR_TYPE) + private String type; + + @Schema(description = "检测工具", example = "卡尺") + @ExcelProperty("检测工具") + private String tool; + + @Schema(description = "结果值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "结果值类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_QC_RESULT_TYPE) + private Integer resultType; + + @Schema(description = "结果值属性", example = "IMG") + @ExcelProperty("结果值属性") + private String resultSpecification; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorSaveReqVO.java new file mode 100644 index 000000000..6c692ef05 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorSaveReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 质检指标新增/修改 Request VO") +@Data +public class MesQcIndicatorSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "检测项编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "QI001") + @NotEmpty(message = "检测项编码不能为空") + private String code; + + @Schema(description = "检测项名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "长度") + @NotEmpty(message = "检测项名称不能为空") + private String name; + + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "SIZE") + @NotEmpty(message = "检测项类型不能为空") + private String type; + + @Schema(description = "检测工具", example = "卡尺") + private String tool; + + @Schema(description = "结果值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "结果值类型不能为空") + private Integer resultType; + + @Schema(description = "结果值属性", example = "IMG") + private String resultSpecification; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcIndicatorResultController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcIndicatorResultController.java new file mode 100644 index 000000000..6591f434c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcIndicatorResultController.java @@ -0,0 +1,184 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.*; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcLineDO; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 检验结果") +@RestController +@RequestMapping("/mes/qc/indicator-result") +@Validated +public class MesQcIndicatorResultController { + + @Resource + private MesQcIndicatorResultService resultService; + @Resource + private MesQcIqcLineService iqcLineService; + @Resource + private MesQcIpqcLineService ipqcLineService; + @Resource + private MesQcOqcLineService oqcLineService; + @Resource + private MesQcRqcLineService rqcLineService; + @Resource + private MesQcIndicatorService indicatorService; + + @PostMapping("/create") + @Operation(summary = "创建检验结果") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:create')") + public CommonResult createIndicatorResult(@Valid @RequestBody MesQcIndicatorResultSaveReqVO createReqVO) { + return success(resultService.createIndicatorResult(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新检验结果") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:update')") + public CommonResult updateIndicatorResult(@Valid @RequestBody MesQcIndicatorResultSaveReqVO updateReqVO) { + resultService.updateIndicatorResult(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除检验结果") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:delete')") + public CommonResult deleteIndicatorResult(@RequestParam("id") Long id) { + resultService.deleteIndicatorResult(id); + return success(true); + } + + @GetMapping("/get-detail") + @Operation(summary = "获得检验结果明细(含检测项模板)") + @Parameters({ + @Parameter(name = "id", description = "检验结果编号(编辑时传入;新增时不传)", example = "1024"), + @Parameter(name = "qcId", description = "质检单ID", required = true, example = "1"), + @Parameter(name = "qcType", description = "质检类型", required = true, example = "1") + }) + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") + public CommonResult getIndicatorResultDetail( + @RequestParam(value = "id", required = false) Long id, + @RequestParam("qcId") Long qcId, + @RequestParam("qcType") Integer qcType) { + MesQcIndicatorResultRespVO respVO; + List details; + if (id != null) { + // 编辑:加载已有结果主表 + 已有明细 + MesQcIndicatorResultDO result = resultService.getIndicatorResult(id); + respVO = BeanUtils.toBean(result, MesQcIndicatorResultRespVO.class); + details = resultService.getIndicatorResultDetailListByResultId(id); + } else { + // 新增:返回空壳 RespVO,仅填充检测项模板 + respVO = new MesQcIndicatorResultRespVO(); + details = Collections.emptyList(); + } + respVO.setItems(buildDetailItemList(details, qcId, qcType)); + return success(respVO); + } + + @GetMapping("/page") + @Operation(summary = "获得检验结果分页") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") + public CommonResult> getIndicatorResultPage(@Valid MesQcIndicatorResultPageReqVO pageReqVO) { + PageResult pageResult = resultService.getIndicatorResultPage(pageReqVO); + // 前端列表只展示 code、sn、remark,无需关联查询 + PageResult voPageResult = BeanUtils.toBean(pageResult, MesQcIndicatorResultRespVO.class); + return success(voPageResult); + } + + // ==================== 拼接 VO ==================== + + /** + * 构建明细 Item 列表 + * + *

前端表单仅需:indicatorId、indicatorName、valueType、valueSpecification + 已有结果(id、value、remark)

+ * + * @param details 已有结果明细(空列表表示获取空值模板) + * @param qcId 质检单 ID + * @param qcType 质检类型 + */ + private List buildDetailItemList( + List details, Long qcId, Integer qcType) { + // 1.1 获取检验单行的指标 ID 列表(知道有哪些检测指标) + List indicatorIds; + if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) { + List lines = iqcLineService.getIqcLineListByIqcId(qcId); + indicatorIds = CollUtil.isEmpty(lines) ? Collections.emptyList() + : new ArrayList<>(convertSet(lines, MesQcIqcLineDO::getIndicatorId)); + } else if (Objects.equals(qcType, MesQcTypeEnum.IPQC.getType())) { + List lines = ipqcLineService.getIpqcLineListByIpqcId(qcId); + indicatorIds = CollUtil.isEmpty(lines) ? Collections.emptyList() + : new ArrayList<>(convertSet(lines, MesQcIpqcLineDO::getIndicatorId)); + } else if (Objects.equals(qcType, MesQcTypeEnum.OQC.getType())) { + List lines = oqcLineService.getOqcLineListByOqcId(qcId); + indicatorIds = CollUtil.isEmpty(lines) ? Collections.emptyList() + : new ArrayList<>(convertSet(lines, MesQcOqcLineDO::getIndicatorId)); + } else if (Objects.equals(qcType, MesQcTypeEnum.RQC.getType())) { + List lines = rqcLineService.getRqcLineListByRqcId(qcId); + indicatorIds = CollUtil.isEmpty(lines) ? Collections.emptyList() + : new ArrayList<>(convertSet(lines, MesQcRqcLineDO::getIndicatorId)); + } else { + throw new IllegalArgumentException("暂不支持 qcType=" + qcType); + } + if (CollUtil.isEmpty(indicatorIds)) { + return Collections.emptyList(); + } + + // 1.2 批量查询检测指标 + Map indicatorMap = indicatorService.getIndicatorMap(new HashSet<>(indicatorIds)); + // 1.3 构建已有明细 Map(按 indicatorId 索引) + Map detailMap = CollUtil.isEmpty(details) + ? Collections.emptyMap() + : convertMap(details, MesQcIndicatorResultDetailDO::getIndicatorId); + + // 2. 遍历指标 ID,组装 VO + List voList = new ArrayList<>(indicatorIds.size()); + for (Long indicatorId : indicatorIds) { + MesQcIndicatorResultRespVO.Item vo = new MesQcIndicatorResultRespVO.Item() + .setIndicatorId(indicatorId); + // 来自 indicator + findAndThen(indicatorMap, indicatorId, indicator -> vo + .setIndicatorName(indicator.getName()) + .setValueType(indicator.getResultType()) + .setValueSpecification(indicator.getResultSpecification())); + // 来自已有结果明细(如有) + findAndThen(detailMap, indicatorId, detail -> vo + .setId(detail.getId()).setResultId(detail.getResultId()) + .setValue(detail.getValue()).setRemark(detail.getRemark())); + voList.add(vo); + } + return voList; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultPageReqVO.java new file mode 100644 index 000000000..cd830cf52 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 检验结果分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcIndicatorResultPageReqVO extends PageParam { + + @Schema(description = "关联质检单ID", example = "1") + private Long qcId; + + @Schema(description = "质检类型", example = "1") + @InEnum(MesQcTypeEnum.class) + private Integer qcType; + + @Schema(description = "样品编号", example = "SPL-001") + private String code; + + @Schema(description = "产品物料ID", example = "1") + private Long itemId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultRespVO.java new file mode 100644 index 000000000..7d81a2b05 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultRespVO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - MES 检验结果 Response VO") +@Data +public class MesQcIndicatorResultRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "样品编号", example = "SPL-001") + private String code; + + @Schema(description = "关联质检单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long qcId; + + @Schema(description = "质检类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer qcType; + + @Schema(description = "产品物料ID", example = "1") + private Long itemId; + + @Schema(description = "物资SN", example = "SN-001") + private String sn; + + @Schema(description = "备注", example = "无") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + // ========== 子表:检验结果明细 ========== + + @Schema(description = "检验结果明细列表") + private List items; + + @Schema(description = "检验结果明细项") + @Data + public static class Item { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "关联检验结果ID", example = "1") + private Long resultId; + + @Schema(description = "检测指标ID", example = "1") + private Long indicatorId; + + @Schema(description = "检测值(统一存为字符串)", example = "3.14") + private String value; + + @Schema(description = "备注", example = "无") + private String remark; + + // ========== 关联查询字段(来自 indicator) ========== + + @Schema(description = "检测指标名称", example = "外观检查") + private String indicatorName; + + @Schema(description = "质检值类型", example = "1") + private Integer valueType; + + @Schema(description = "值属性", example = "IMG") + private String valueSpecification; + + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultSaveReqVO.java new file mode 100644 index 000000000..d784c3d15 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcIndicatorResultSaveReqVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - MES 检验结果创建/更新 Request VO") +@Data +public class MesQcIndicatorResultSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "样品编号", example = "SPL-001") + private String code; + + @Schema(description = "关联质检单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "关联质检单ID不能为空") + private Long qcId; + + @Schema(description = "质检类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "质检类型不能为空") + @InEnum(MesQcTypeEnum.class) + private Integer qcType; + + @Schema(description = "物资SN", example = "SN-001") + private String sn; + + @Schema(description = "备注", example = "无") + private String remark; + + @Schema(description = "检验结果明细列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "检验结果明细列表不能为空") + private List items; + + @Schema(description = "检验结果明细项") + @Data + public static class Item { + + @Schema(description = "编号(更新时传入已有明细的 ID)", example = "1024") + private Long id; + + @Schema(description = "检测指标ID", example = "1") + private Long indicatorId; + + @Schema(description = "检测值(统一存为字符串)", example = "3.14") + private String value; + + @Schema(description = "备注", example = "无") + private String remark; + + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java new file mode 100644 index 000000000..3e1c52ba3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcController.java @@ -0,0 +1,173 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.qc.ipqc.vo.MesQcIpqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; +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.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +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.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 过程检验单(IPQC)") +@RestController +@RequestMapping("/mes/qc/ipqc") +@Validated +public class MesQcIpqcController { + + @Resource + private MesQcIpqcService ipqcService; + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesProProcessService processService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建过程检验单") + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:create')") + public CommonResult createIpqc(@Valid @RequestBody MesQcIpqcSaveReqVO createReqVO) { + return success(ipqcService.createIpqc(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新过程检验单") + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:update')") + public CommonResult updateIpqc(@Valid @RequestBody MesQcIpqcSaveReqVO updateReqVO) { + ipqcService.updateIpqc(updateReqVO); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成过程检验单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:finish')") + public CommonResult finishIpqc(@RequestParam("id") Long id) { + ipqcService.finishIpqc(id); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除过程检验单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:delete')") + public CommonResult deleteIpqc(@RequestParam("id") Long id) { + ipqcService.deleteIpqc(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得过程检验单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:query')") + public CommonResult getIpqc(@RequestParam("id") Long id) { + MesQcIpqcDO ipqc = ipqcService.getIpqc(id); + return success(buildIpqcRespVOList(Collections.singletonList(ipqc)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得过程检验单分页") + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:query')") + public CommonResult> getIpqcPage(@Valid MesQcIpqcPageReqVO pageReqVO) { + PageResult pageResult = ipqcService.getIpqcPage(pageReqVO); + return success(new PageResult<>(buildIpqcRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出过程检验单 Excel") + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportIpqcExcel(@Valid MesQcIpqcPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = ipqcService.getIpqcPage(pageReqVO).getList(); + List voList = buildIpqcRespVOList(list); + ExcelUtils.write(response, "过程检验单.xls", "数据", MesQcIpqcRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + private List buildIpqcRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询工单 + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesQcIpqcDO::getWorkOrderId)); + // 批量查询工位 + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesQcIpqcDO::getWorkstationId)); + // 批量查询工序 + Map processMap = processService.getProcessMap( + convertSet(list, MesQcIpqcDO::getProcessId)); + // 批量查询物料 + Map itemMap = itemService.getItemMap( + convertSet(list, MesQcIpqcDO::getItemId)); + // 批量查询计量单位( + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 批量查询检测人员 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesQcIpqcDO::getInspectorUserId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcIpqcRespVO.class, vo -> { + findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder -> vo + .setWorkOrderCode(workOrder.getCode()).setWorkOrderName(workOrder.getName())); + findAndThen(workstationMap, vo.getWorkstationId(), + ws -> vo.setWorkstationName(ws.getName())); + findAndThen(processMap, vo.getProcessId(), + process -> vo.setProcessName(process.getName())); + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unit -> vo.setUnitName(unit.getName())); + }); + findAndThen(userMap, vo.getInspectorUserId(), + user -> vo.setInspectorNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcLineController.java new file mode 100644 index 000000000..61b5bd60b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/MesQcIpqcLineController.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLineRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 过程检验单行") +@RestController +@RequestMapping("/mes/qc/ipqc/line") +@Validated +public class MesQcIpqcLineController { + + @Resource + private MesQcIpqcLineService ipqcLineService; + @Resource + private MesQcIndicatorService indicatorService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @GetMapping("/get") + @Operation(summary = "获得过程检验单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:query')") + public CommonResult getIpqcLine(@RequestParam("id") Long id) { + MesQcIpqcLineDO line = ipqcLineService.getIpqcLine(id); + return success(buildLineRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得过程检验单行分页") + @PreAuthorize("@ss.hasPermission('mes:qc-ipqc:query')") + public CommonResult> getIpqcLinePage(@Valid MesQcIpqcLinePageReqVO pageReqVO) { + PageResult pageResult = ipqcLineService.getIpqcLinePage(pageReqVO); + return success(new PageResult<>(buildLineRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildLineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询检测指标 + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(list, MesQcIpqcLineDO::getIndicatorId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(list, MesQcIpqcLineDO::getUnitMeasureId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcIpqcLineRespVO.class, vo -> { + findAndThen(indicatorMap, vo.getIndicatorId(), indicator -> + vo.setIndicatorCode(indicator.getCode()).setIndicatorName(indicator.getName()) + .setIndicatorType(indicator.getType())); + findAndThen(unitMeasureMap, vo.getUnitMeasureId(), + unit -> vo.setUnitMeasureName(unit.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java new file mode 100644 index 000000000..a856a0a33 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcPageReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 过程检验单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcIpqcPageReqVO extends PageParam { + + @Schema(description = "检验单编号", example = "IPQC2025") + private String code; + + @Schema(description = "IPQC 检验类型", example = "1") + private Integer type; + + @Schema(description = "生产工单 ID", example = "10") + private Long workOrderId; + + @Schema(description = "产品物料 ID", example = "50") + private Long itemId; + + @Schema(description = "检测结果", example = "1") + private Integer checkResult; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "检测人员用户 ID", example = "1") + private Long inspectorUserId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java new file mode 100644 index 000000000..10bd8a3a7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java @@ -0,0 +1,172 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 过程检验单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcIpqcRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPQC20250101001") + @ExcelProperty("检验单编号") + private String code; + + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "XX工单过程检验") + @ExcelProperty("检验单名称") + private String name; + + @Schema(description = "IPQC 检验类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("检验类型") + private Integer type; + + @Schema(description = "检验模板 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long templateId; + + // ========== 来源单据 ========== + + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + + @Schema(description = "来源单据类型", example = "304") + private Integer sourceDocType; + + @Schema(description = "来源单据行 ID", example = "300") + private Long sourceLineId; + + @Schema(description = "来源单据编号", example = "FB20250101001") + private String sourceDocCode; + + // ========== 生产关联 ========== + + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long workOrderId; + + @Schema(description = "工单编号", example = "WO20250101001") + @ExcelProperty("工单编号") + private String workOrderCode; + + @Schema(description = "工单名称", example = "生产工单A") + private String workOrderName; + + @Schema(description = "生产任务 ID", example = "20") + private Long taskId; + + @Schema(description = "工位 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") + private Long workstationId; + + @Schema(description = "工位名称", example = "工位A") + @ExcelProperty("工位名称") + private String workstationName; + + @Schema(description = "工序 ID", example = "40") + private Long processId; + + @Schema(description = "工序名称", example = "组装") + @ExcelProperty("工序名称") + private String processName; + + // ========== 物料 ========== + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") + private Long itemId; + + @Schema(description = "产品物料编码", example = "ITEM001") + @ExcelProperty("产品物料编码") + private String itemCode; + + @Schema(description = "产品物料名称", example = "物料A") + @ExcelProperty("产品物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "100mm*50mm") + private String itemSpecification; + + @Schema(description = "单位名称", example = "个") + private String unitName; + + // ========== 数量 ========== + + @Schema(description = "检测数量", example = "100") + @ExcelProperty("检测数量") + private BigDecimal checkQuantity; + + @Schema(description = "合格品数量", example = "95") + @ExcelProperty("合格品数量") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不合格品数量", example = "5") + @ExcelProperty("不合格品数量") + private BigDecimal unqualifiedQuantity; + + @Schema(description = "工废数量", example = "2") + @ExcelProperty("工废数量") + private BigDecimal laborScrapQuantity; + + @Schema(description = "料废数量", example = "2") + @ExcelProperty("料废数量") + private BigDecimal materialScrapQuantity; + + @Schema(description = "其他废品数量", example = "1") + @ExcelProperty("其他废品数量") + private BigDecimal otherScrapQuantity; + + // ========== 缺陷统计 ========== + + @Schema(description = "致命缺陷率(%)", example = "0.00") + private BigDecimal criticalRate; + + @Schema(description = "严重缺陷率(%)", example = "0.00") + private BigDecimal majorRate; + + @Schema(description = "轻微缺陷率(%)", example = "10.00") + private BigDecimal minorRate; + + @Schema(description = "致命缺陷数量", example = "0") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "0") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "1") + private Integer minorQuantity; + + // ========== 检验 ========== + + @Schema(description = "检测结果", example = "1") + @ExcelProperty("检测结果") + private Integer checkResult; + + @Schema(description = "检测日期") + @ExcelProperty("检测日期") + private LocalDateTime inspectDate; + + @Schema(description = "检测人员用户 ID", example = "1") + private Long inspectorUserId; + + @Schema(description = "检测人员昵称", example = "张三") + @ExcelProperty("检测人员") + private String inspectorNickname; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java new file mode 100644 index 000000000..433765d3a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcSaveReqVO.java @@ -0,0 +1,131 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo; + +import cn.hutool.core.util.ObjUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 过程检验单新增/修改 Request VO") +@Data +public class MesQcIpqcSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPQC20250101001") + @NotEmpty(message = "检验单编号不能为空") + private String code; + + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "XX工单过程检验") + @NotEmpty(message = "检验单名称不能为空") + private String name; + + @Schema(description = "IPQC 检验类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检验类型不能为空") + private Integer type; + + // ========== 来源单据 ========== + + @Schema(description = "来源单据类型", example = "304") + private Integer sourceDocType; + + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + + @Schema(description = "来源单据行 ID", example = "300") + private Long sourceLineId; + + // ========== 生产关联 ========== + + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "生产工单不能为空") + private Long workOrderId; + + @Schema(description = "生产任务 ID", example = "20") + private Long taskId; + + @Schema(description = "工位 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") + @NotNull(message = "工位不能为空") + private Long workstationId; + + @Schema(description = "工序 ID", example = "40") + private Long processId; + + // ========== 物料 ========== + + @Schema(description = "产品物料 ID", example = "50") + private Long itemId; + + // ========== 数量 ========== + + @Schema(description = "检测数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "检测数量不能为空") + @DecimalMin(value = "0", message = "检测数量不能小于 0") + private BigDecimal checkQuantity; + + @Schema(description = "合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "95") + @NotNull(message = "合格品数量不能为空") + @DecimalMin(value = "0", message = "合格品数量不能小于 0") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") + @NotNull(message = "不合格品数量不能为空") + @DecimalMin(value = "0", message = "不合格品数量不能小于 0") + private BigDecimal unqualifiedQuantity; + + @Schema(description = "工废数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "工废数量不能为空") + @DecimalMin(value = "0", message = "工废数量不能小于 0") + private BigDecimal laborScrapQuantity; + + @Schema(description = "料废数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "料废数量不能为空") + @DecimalMin(value = "0", message = "料废数量不能小于 0") + private BigDecimal materialScrapQuantity; + + @Schema(description = "其他废品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "其他废品数量不能为空") + @DecimalMin(value = "0", message = "其他废品数量不能小于 0") + private BigDecimal otherScrapQuantity; + + // ========== 检验 ========== + + @Schema(description = "检测结果", example = "1") + private Integer checkResult; + + @Schema(description = "检测日期") + private LocalDateTime inspectDate; + + @Schema(description = "检测人员用户 ID", example = "1") + private Long inspectorUserId; + + @Schema(description = "备注", example = "备注") + private String remark; + + @AssertTrue(message = "检测数量必须等于合格品数量与不合格品数量之和") + @JsonIgnore + public boolean isQuantityValid() { + if (ObjUtil.hasNull(checkQuantity, qualifiedQuantity, unqualifiedQuantity)) { + return true; // @NotNull 会处理 null + } + return checkQuantity.compareTo(qualifiedQuantity.add(unqualifiedQuantity)) == 0; + } + + @AssertTrue(message = "工废、料废、其他废品数量之和不能超过不合格品数量") + @JsonIgnore + public boolean isScrapQuantityValid() { + if (ObjUtil.hasNull(unqualifiedQuantity, laborScrapQuantity, materialScrapQuantity, otherScrapQuantity)) { + return true; // @NotNull 会处理 null + } + BigDecimal scrapSum = laborScrapQuantity.add(materialScrapQuantity).add(otherScrapQuantity); + return scrapSum.compareTo(unqualifiedQuantity) <= 0; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLinePageReqVO.java new file mode 100644 index 000000000..92eba2836 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 过程检验单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcIpqcLinePageReqVO extends PageParam { + + @Schema(description = "过程检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "过程检验单 ID 不能为空") + private Long ipqcId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLineRespVO.java new file mode 100644 index 000000000..dba702073 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLineRespVO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 过程检验单行 Response VO") +@Data +@Accessors(chain = true) +public class MesQcIpqcLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "过程检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long ipqcId; + + @Schema(description = "检测指标 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long indicatorId; + + @Schema(description = "检测指标编码", example = "IND001") + private String indicatorCode; + + @Schema(description = "检测指标名称", example = "外观") + private String indicatorName; + + @Schema(description = "检测指标类型", example = "QUANTITATIVE") + private String indicatorType; + + @Schema(description = "检测工具", example = "卡尺") + private String tool; + + @Schema(description = "检测方法", example = "目测") + private String checkMethod; + + @Schema(description = "标准值", example = "10.5000") + private BigDecimal standardValue; + + @Schema(description = "计量单位 ID", example = "3") + private Long unitMeasureId; + + @Schema(description = "计量单位名称", example = "毫米") + private String unitMeasureName; + + @Schema(description = "误差上限", example = "11.0000") + private BigDecimal maxThreshold; + + @Schema(description = "误差下限", example = "10.0000") + private BigDecimal minThreshold; + + @Schema(description = "致命缺陷数量", example = "0") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "0") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "1") + private Integer minorQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java new file mode 100644 index 000000000..160216077 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java @@ -0,0 +1,158 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.iqc; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.qc.iqc.vo.MesQcIqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcSaveReqVO; +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.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +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.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - MES 来料检验单(IQC)") +@RestController +@RequestMapping("/mes/qc/iqc") +@Validated +public class MesQcIqcController { + + @Resource + private MesQcIqcService iqcService; + @Resource + private MesMdVendorService vendorService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建来料检验单") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:create')") + public CommonResult createIqc(@Valid @RequestBody MesQcIqcSaveReqVO createReqVO) { + return success(iqcService.createIqc(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新来料检验单") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:update')") + public CommonResult updateIqc(@Valid @RequestBody MesQcIqcSaveReqVO updateReqVO) { + iqcService.updateIqc(updateReqVO); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成来料检验单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:finish')") + public CommonResult finishIqc(@RequestParam("id") Long id) { + iqcService.finishIqc(id); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除来料检验单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:delete')") + public CommonResult deleteIqc(@RequestParam("id") Long id) { + iqcService.deleteIqc(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得来料检验单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") + public CommonResult getIqc(@RequestParam("id") Long id) { + MesQcIqcDO iqc = iqcService.getIqc(id); + return success(buildIqcRespVOList(Collections.singletonList(iqc)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得来料检验单分页") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") + public CommonResult> getIqcPage(@Valid MesQcIqcPageReqVO pageReqVO) { + PageResult pageResult = iqcService.getIqcPage(pageReqVO); + return success(new PageResult<>(buildIqcRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出来料检验单 Excel") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportIqcExcel(@Valid MesQcIqcPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = iqcService.getIqcPage(pageReqVO).getList(); + List voList = buildIqcRespVOList(list); + ExcelUtils.write(response, "来料检验单.xls", "数据", MesQcIqcRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + private List buildIqcRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询供应商 + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesQcIqcDO::getVendorId)); + // 批量查询物料 + Map itemMap = itemService.getItemMap( + convertSet(list, MesQcIqcDO::getItemId)); + // 批量查询计量单位(通过物料的 unitMeasureId) + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 批量查询检测人员 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesQcIqcDO::getInspectorUserId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcIqcRespVO.class, vo -> { + findAndThen(vendorMap, vo.getVendorId(), + vendor -> vo.setVendorNickname(vendor.getNickname())); + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()); + vo.setItemName(item.getName()); + vo.setItemSpecification(item.getSpecification()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unit -> vo.setUnitName(unit.getName())); + }); + findAndThen(userMap, vo.getInspectorUserId(), + user -> vo.setInspectorNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcLineController.java new file mode 100644 index 000000000..10ea27737 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcLineController.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.iqc; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLineRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 来料检验单行") +@RestController +@RequestMapping("/mes/qc/iqc/line") +@Validated +public class MesQcIqcLineController { + + @Resource + private MesQcIqcLineService iqcLineService; + @Resource + private MesQcIndicatorService indicatorService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @GetMapping("/get") + @Operation(summary = "获得来料检验单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") + public CommonResult getIqcLine(@RequestParam("id") Long id) { + MesQcIqcLineDO line = iqcLineService.getIqcLine(id); + return success(buildLineRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得来料检验单行分页") + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") + public CommonResult> getIqcLinePage(@Valid MesQcIqcLinePageReqVO pageReqVO) { + PageResult pageResult = iqcLineService.getIqcLinePage(pageReqVO); + return success(new PageResult<>(buildLineRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildLineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询检测指标 + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(list, MesQcIqcLineDO::getIndicatorId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(list, MesQcIqcLineDO::getUnitMeasureId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcIqcLineRespVO.class, vo -> { + findAndThen(indicatorMap, vo.getIndicatorId(), indicator -> + vo.setIndicatorCode(indicator.getCode()).setIndicatorName(indicator.getName()) + .setIndicatorType(indicator.getType())); + findAndThen(unitMeasureMap, vo.getUnitMeasureId(), + unit -> vo.setUnitMeasureName(unit.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcPageReqVO.java new file mode 100644 index 000000000..dfd6f34bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcPageReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 来料检验单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcIqcPageReqVO extends PageParam { + + @Schema(description = "检验单编号", example = "IQC2025") + private String code; + + @Schema(description = "供应商 ID", example = "10") + private Long vendorId; + + @Schema(description = "供应商批次号", example = "VB2025") + private String vendorBatch; + + @Schema(description = "产品物料 ID", example = "20") + private Long itemId; + + @Schema(description = "检测结果", example = "1") + private Integer checkResult; + + @Schema(description = "检测人员用户 ID", example = "1") + private Long inspectorUserId; + + @Schema(description = "来料日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] receiveDate; + + @Schema(description = "检测日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] inspectDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java new file mode 100644 index 000000000..ab51d361b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java @@ -0,0 +1,147 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 来料检验单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcIqcRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "IQC20250101001") + @ExcelProperty("检验单编号") + private String code; + + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料A来料检验") + @ExcelProperty("检验单名称") + private String name; + + @Schema(description = "检验模板 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long templateId; + + // ========== 来源单据 ========== + + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + + @Schema(description = "来源单据类型", example = "100") + private Integer sourceDocType; + + @Schema(description = "来源单据行 ID", example = "300") + private Long sourceLineId; + + @Schema(description = "来源单据编号", example = "DOC20250101001") + private String sourceDocCode; + + // ========== 供应商 ========== + + @Schema(description = "供应商 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long vendorId; + + @Schema(description = "供应商简称", example = "供应商A") + private String vendorNickname; + + @Schema(description = "供应商批次号", example = "VB20250101") + @ExcelProperty("供应商批次号") + private String vendorBatch; + + // ========== 物料 ========== + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + private Long itemId; + + @Schema(description = "产品物料编码", example = "ITEM001") + @ExcelProperty("产品物料编码") + private String itemCode; + + @Schema(description = "产品物料名称", example = "物料A") + @ExcelProperty("产品物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "100mm*50mm") + private String itemSpecification; + + @Schema(description = "单位名称", example = "个") + private String unitName; + + // ========== 数量 ========== + + @Schema(description = "本次接收数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @ExcelProperty("接收数量") + private BigDecimal receivedQuantity; + + @Schema(description = "本次检测数量", example = "10") + @ExcelProperty("检测数量") + private BigDecimal checkQuantity; + + @Schema(description = "合格品数量", example = "9") + @ExcelProperty("合格品数量") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不合格品数量", example = "1") + @ExcelProperty("不合格品数量") + private BigDecimal unqualifiedQuantity; + + // ========== 缺陷统计 ========== + + @Schema(description = "致命缺陷率(%)", example = "0.00") + private BigDecimal criticalRate; + + @Schema(description = "严重缺陷率(%)", example = "0.00") + private BigDecimal majorRate; + + @Schema(description = "轻微缺陷率(%)", example = "10.00") + private BigDecimal minorRate; + + @Schema(description = "致命缺陷数量", example = "0") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "0") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "1") + private Integer minorQuantity; + + // ========== 检验 ========== + + @Schema(description = "检测结果", example = "1") + @ExcelProperty("检测结果") + private Integer checkResult; + + @Schema(description = "来料日期") + @ExcelProperty("来料日期") + private LocalDateTime receiveDate; + + @Schema(description = "检测日期") + @ExcelProperty("检测日期") + private LocalDateTime inspectDate; + + @Schema(description = "检测人员用户 ID", example = "1") + private Long inspectorUserId; + + @Schema(description = "检测人员昵称", example = "张三") + @ExcelProperty("检测人员") + private String inspectorNickname; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java new file mode 100644 index 000000000..fab8802aa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo; + +import cn.hutool.core.util.ObjUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 来料检验单新增/修改 Request VO") +@Data +public class MesQcIqcSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "IQC20250101001") + @NotEmpty(message = "检验单编号不能为空") + private String code; + + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料A来料检验") + @NotEmpty(message = "检验单名称不能为空") + private String name; + + // ========== 来源单据 ========== + + @Schema(description = "来源单据类型", example = "100") + private Integer sourceDocType; + + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + + @Schema(description = "来源单据行 ID", example = "300") + private Long sourceLineId; + + // ========== 供应商 ========== + + @Schema(description = "供应商 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "供应商不能为空") + private Long vendorId; + + @Schema(description = "供应商批次号", example = "VB20250101") + private String vendorBatch; + + // ========== 物料 ========== + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + @NotNull(message = "产品物料不能为空") + private Long itemId; + + // ========== 数量 ========== + + @Schema(description = "本次接收数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "本次接收数量不能为空") + private BigDecimal receivedQuantity; + + @Schema(description = "合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "9") + @NotNull(message = "合格品数量不能为空") + @DecimalMin(value = "0", message = "合格品数量不能小于 0") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "不合格品数量不能为空") + @DecimalMin(value = "0", message = "不合格品数量不能小于 0") + private BigDecimal unqualifiedQuantity; + + // ========== 检验 ========== + + @Schema(description = "检测人员用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检测人员不能为空") + private Long inspectorUserId; + + @Schema(description = "检测日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "检测日期不能为空") + private LocalDateTime inspectDate; + + @Schema(description = "检测结果", example = "1") + private Integer checkResult; + + @Schema(description = "来料日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "来料日期不能为空") + private LocalDateTime receiveDate; + + @Schema(description = "备注", example = "备注") + private String remark; + + @AssertTrue(message = "合格品数量与不合格品数量之和必须等于本次接收数量") + @JsonIgnore + public boolean isQuantityValid() { + if (ObjUtil.hasNull(qualifiedQuantity, unqualifiedQuantity, receivedQuantity)) { + return true; // @NotNull 会处理 null + } + return qualifiedQuantity.add(unqualifiedQuantity).compareTo(receivedQuantity) == 0; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLinePageReqVO.java new file mode 100644 index 000000000..d9a3fe65a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 来料检验单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcIqcLinePageReqVO extends PageParam { + + @Schema(description = "来料检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "来料检验单 ID 不能为空") + private Long iqcId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLineRespVO.java new file mode 100644 index 000000000..d8170aee9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLineRespVO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 来料检验单行 Response VO") +@Data +@Accessors(chain = true) +public class MesQcIqcLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "来料检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long iqcId; + + @Schema(description = "检测指标 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long indicatorId; + + @Schema(description = "检测指标编码", example = "IND001") + private String indicatorCode; + + @Schema(description = "检测指标名称", example = "外观") + private String indicatorName; + + @Schema(description = "检测指标类型", example = "QUANTITATIVE") + private String indicatorType; + + @Schema(description = "检测工具", example = "卡尺") + private String tool; + + @Schema(description = "检测方法", example = "目测") + private String checkMethod; + + @Schema(description = "标准值", example = "10.5000") + private BigDecimal standardValue; + + @Schema(description = "计量单位 ID", example = "3") + private Long unitMeasureId; + + @Schema(description = "计量单位名称", example = "毫米") + private String unitMeasureName; + + @Schema(description = "误差上限", example = "11.0000") + private BigDecimal maxThreshold; + + @Schema(description = "误差下限", example = "10.0000") + private BigDecimal minThreshold; + + @Schema(description = "致命缺陷数量", example = "0") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "0") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "1") + private Integer minorQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java new file mode 100644 index 000000000..279ba1e10 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcController.java @@ -0,0 +1,155 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.oqc; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.qc.oqc.vo.MesQcOqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +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.qc.oqc.MesQcOqcDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +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.qc.oqc.MesQcOqcService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 出货检验单(OQC)") +@RestController +@RequestMapping("/mes/qc/oqc") +@Validated +public class MesQcOqcController { + + @Resource + private MesQcOqcService oqcService; + @Resource + private MesMdClientService clientService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建出货检验单") + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:create')") + public CommonResult createOqc(@Valid @RequestBody MesQcOqcSaveReqVO createReqVO) { + return success(oqcService.createOqc(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新出货检验单") + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:update')") + public CommonResult updateOqc(@Valid @RequestBody MesQcOqcSaveReqVO updateReqVO) { + oqcService.updateOqc(updateReqVO); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成出货检验单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:finish')") + public CommonResult finishOqc(@RequestParam("id") Long id) { + oqcService.finishOqc(id); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除出货检验单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:delete')") + public CommonResult deleteOqc(@RequestParam("id") Long id) { + oqcService.deleteOqc(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得出货检验单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:query')") + public CommonResult getOqc(@RequestParam("id") Long id) { + MesQcOqcDO oqc = oqcService.getOqc(id); + return success(buildOqcRespVOList(Collections.singletonList(oqc)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得出货检验单分页") + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:query')") + public CommonResult> getOqcPage(@Valid MesQcOqcPageReqVO pageReqVO) { + PageResult pageResult = oqcService.getOqcPage(pageReqVO); + return success(new PageResult<>(buildOqcRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出出货检验单 Excel") + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportOqcExcel(@Valid MesQcOqcPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = oqcService.getOqcPage(pageReqVO).getList(); + List voList = buildOqcRespVOList(list); + ExcelUtils.write(response, "出货检验单.xls", "数据", MesQcOqcRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + private List buildOqcRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询客户 + Map clientMap = clientService.getClientMap( + convertSet(list, MesQcOqcDO::getClientId)); + // 批量查询物料 + Map itemMap = itemService.getItemMap( + convertSet(list, MesQcOqcDO::getItemId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 批量查询检测人员 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesQcOqcDO::getInspectorUserId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcOqcRespVO.class, vo -> { + findAndThen(clientMap, vo.getClientId(), + client -> vo.setClientNickname(client.getNickname())); + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unit -> vo.setUnitName(unit.getName())); + }); + findAndThen(userMap, vo.getInspectorUserId(), + user -> vo.setInspectorNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcLineController.java new file mode 100644 index 000000000..597306118 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/MesQcOqcLineController.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.oqc; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.line.MesQcOqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.line.MesQcOqcLineRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 出货检验单行") +@RestController +@RequestMapping("/mes/qc/oqc/line") +@Validated +public class MesQcOqcLineController { + + @Resource + private MesQcOqcLineService oqcLineService; + @Resource + private MesQcIndicatorService indicatorService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @GetMapping("/get") + @Operation(summary = "获得出货检验单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:query')") + public CommonResult getOqcLine(@RequestParam("id") Long id) { + MesQcOqcLineDO line = oqcLineService.getOqcLine(id); + return success(buildLineRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得出货检验单行分页") + @PreAuthorize("@ss.hasPermission('mes:qc-oqc:query')") + public CommonResult> getOqcLinePage(@Valid MesQcOqcLinePageReqVO pageReqVO) { + PageResult pageResult = oqcLineService.getOqcLinePage(pageReqVO); + return success(new PageResult<>(buildLineRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildLineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询检测指标 + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(list, MesQcOqcLineDO::getIndicatorId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(list, MesQcOqcLineDO::getUnitMeasureId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcOqcLineRespVO.class, vo -> { + findAndThen(indicatorMap, vo.getIndicatorId(), indicator -> + vo.setIndicatorCode(indicator.getCode()).setIndicatorName(indicator.getName()) + .setIndicatorType(indicator.getType())); + findAndThen(unitMeasureMap, vo.getUnitMeasureId(), + unit -> vo.setUnitMeasureName(unit.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcPageReqVO.java new file mode 100644 index 000000000..47926c101 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 出货检验单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcOqcPageReqVO extends PageParam { + + @Schema(description = "检验单编号", example = "OQC2025") + private String code; + + @Schema(description = "客户 ID", example = "10") + private Long clientId; + + @Schema(description = "批次号", example = "BC2025") + private String batchCode; + + @Schema(description = "产品物料 ID", example = "20") + private Long itemId; + + @Schema(description = "检测结果", example = "1") + private Integer checkResult; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java new file mode 100644 index 000000000..8c314bb02 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java @@ -0,0 +1,154 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 出货检验单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcOqcRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "OQC20250101001") + @ExcelProperty("检验单编号") + private String code; + + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料A出货检验") + @ExcelProperty("检验单名称") + private String name; + + @Schema(description = "检验模板 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long templateId; + + // ========== 来源单据 ========== + + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + + @Schema(description = "来源单据类型", example = "118") + private Integer sourceDocType; + + @Schema(description = "来源单据行 ID", example = "300") + private Long sourceLineId; + + @Schema(description = "来源单据编号", example = "DOC20250101001") + private String sourceDocCode; + + // ========== 客户 ========== + + @Schema(description = "客户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long clientId; + + @Schema(description = "客户简称", example = "客户A") + @ExcelProperty("客户简称") + private String clientNickname; + + @Schema(description = "批次号", example = "BC20250101") + @ExcelProperty("批次号") + private String batchCode; + + // ========== 物料 ========== + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + private Long itemId; + + @Schema(description = "产品物料编码", example = "ITEM001") + @ExcelProperty("产品物料编码") + private String itemCode; + + @Schema(description = "产品物料名称", example = "物料A") + @ExcelProperty("产品物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "100mm*50mm") + private String itemSpecification; + + @Schema(description = "单位名称", example = "个") + private String unitName; + + // ========== 数量 ========== + + @Schema(description = "最低检测数", example = "5") + private Integer minCheckQuantity; + + @Schema(description = "最大不合格数", example = "0") + private Integer maxUnqualifiedQuantity; + + @Schema(description = "本次出货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @ExcelProperty("出货数量") + private BigDecimal outQuantity; + + @Schema(description = "本次检测数量", example = "10") + @ExcelProperty("检测数量") + private BigDecimal checkQuantity; + + @Schema(description = "合格品数量", example = "9") + @ExcelProperty("合格品数量") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不合格品数量", example = "1") + @ExcelProperty("不合格品数量") + private BigDecimal unqualifiedQuantity; + + // ========== 缺陷统计 ========== + + @Schema(description = "致命缺陷率(%)", example = "0.00") + private BigDecimal criticalRate; + + @Schema(description = "严重缺陷率(%)", example = "0.00") + private BigDecimal majorRate; + + @Schema(description = "轻微缺陷率(%)", example = "10.00") + private BigDecimal minorRate; + + @Schema(description = "致命缺陷数量", example = "0") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "0") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "1") + private Integer minorQuantity; + + // ========== 检验 ========== + + @Schema(description = "检测结果", example = "1") + @ExcelProperty("检测结果") + private Integer checkResult; + + @Schema(description = "出货日期") + @ExcelProperty("出货日期") + private LocalDateTime outDate; + + @Schema(description = "检测日期") + @ExcelProperty("检测日期") + private LocalDateTime inspectDate; + + @Schema(description = "检测人员用户 ID", example = "1") + private Long inspectorUserId; + + @Schema(description = "检测人员昵称", example = "张三") + @ExcelProperty("检测人员") + private String inspectorNickname; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java new file mode 100644 index 000000000..d4ecc07d2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo; + +import cn.hutool.core.util.ObjUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.*; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 出货检验单新增/修改 Request VO") +@Data +public class MesQcOqcSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "OQC20250101001") + @NotEmpty(message = "检验单编号不能为空") + private String code; + + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料A出货检验") + @NotEmpty(message = "检验单名称不能为空") + private String name; + + // ========== 来源单据 ========== + + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + + @Schema(description = "来源单据类型", example = "118") + private Integer sourceDocType; + + @Schema(description = "来源单据行 ID", example = "300") + private Long sourceLineId; + + // ========== 客户 ========== + + @Schema(description = "客户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "客户不能为空") + private Long clientId; + + @Schema(description = "批次号", example = "BC20250101") + private String batchCode; + + // ========== 物料 ========== + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + @NotNull(message = "产品物料不能为空") + private Long itemId; + + // ========== 数量 ========== + + @Schema(description = "本次出货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "本次出货数量不能为空") + @DecimalMin(value = "0", message = "本次出货数量不能小于 0") + private BigDecimal outQuantity; + + @Schema(description = "本次检测数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "本次检测数量不能为空") + @DecimalMin(value = "0", message = "本次检测数量不能小于 0") + private BigDecimal checkQuantity; + + @Schema(description = "合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "9") + @NotNull(message = "合格品数量不能为空") + @DecimalMin(value = "0", message = "合格品数量不能小于 0") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "不合格品数量不能为空") + @DecimalMin(value = "0", message = "不合格品数量不能小于 0") + private BigDecimal unqualifiedQuantity; + + // ========== 检验 ========== + + @Schema(description = "检测人员用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检测人员不能为空") + private Long inspectorUserId; + + @Schema(description = "出货日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出货日期不能为空") + private LocalDateTime outDate; + + @Schema(description = "检测日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "检测日期不能为空") + private LocalDateTime inspectDate; + + @Schema(description = "检测结果", example = "1") + private Integer checkResult; + + @Schema(description = "备注", example = "备注") + private String remark; + + @AssertTrue(message = "检测数量必须等于合格品数量与不合格品数量之和") + @JsonIgnore + public boolean isQuantityValid() { + if (ObjUtil.hasNull(checkQuantity, qualifiedQuantity, unqualifiedQuantity)) { + return true; // @NotNull 会处理 null + } + return checkQuantity.compareTo(qualifiedQuantity.add(unqualifiedQuantity)) == 0; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLinePageReqVO.java new file mode 100644 index 000000000..be83e18c6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 出货检验单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcOqcLinePageReqVO extends PageParam { + + @Schema(description = "出货检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "出货检验单 ID 不能为空") + private Long oqcId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLineRespVO.java new file mode 100644 index 000000000..ae69409a6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLineRespVO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 出货检验单行 Response VO") +@Data +@Accessors(chain = true) +public class MesQcOqcLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "出货检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long oqcId; + + @Schema(description = "检测指标 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long indicatorId; + + @Schema(description = "检测指标编码", example = "IND001") + private String indicatorCode; + + @Schema(description = "检测指标名称", example = "外观") + private String indicatorName; + + @Schema(description = "检测指标类型", example = "QUANTITATIVE") + private String indicatorType; + + @Schema(description = "检测工具", example = "卡尺") + private String tool; + + @Schema(description = "检测方法", example = "目测") + private String checkMethod; + + @Schema(description = "标准值", example = "10.5000") + private BigDecimal standardValue; + + @Schema(description = "计量单位 ID", example = "3") + private Long unitMeasureId; + + @Schema(description = "计量单位名称", example = "毫米") + private String unitMeasureName; + + @Schema(description = "误差上限", example = "11.0000") + private BigDecimal maxThreshold; + + @Schema(description = "误差下限", example = "10.0000") + private BigDecimal minThreshold; + + @Schema(description = "致命缺陷数量", example = "0") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "0") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "1") + private Integer minorQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/package-info.java new file mode 100644 index 000000000..f515770f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/package-info.java @@ -0,0 +1,4 @@ +/** + * MES 质量管理(Quality Control):检验模板、质检指标、来料检(IQC)、过程检(IPQC)、出货检(OQC)、退货检(RQC)、缺陷管理 + */ +package cn.iocoder.yudao.module.mes.controller.admin.qc; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/MesQcPendingInspectController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/MesQcPendingInspectController.java new file mode 100644 index 000000000..65f6b13bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/MesQcPendingInspectController.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +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.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +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.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; +import cn.iocoder.yudao.module.mes.service.qc.pendinginspect.MesQcPendingInspectService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 待检任务") +@RestController +@RequestMapping("/mes/qc/pending-inspect") +@Validated +public class MesQcPendingInspectController { + + @Resource + private MesQcPendingInspectService pendingInspectService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesMdVendorService vendorService; + @Resource + private MesMdClientService clientService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesProTaskService taskService; + + @GetMapping("/page") + @Operation(summary = "获得待检任务分页") + @PreAuthorize("@ss.hasPermission('mes:qc-pending-inspect:query')") + public CommonResult> getPendingInspectPage( + @Valid MesQcPendingInspectPageReqVO pageReqVO) { + PageResult pageResult = pendingInspectService.getPendingInspectPage(pageReqVO); + // 拼接 VO:物料、供应商、客户、工作站、任务等 + buildPendingInspectRespVOList(pageResult.getList()); + return success(pageResult); + } + + // ==================== 拼接 VO ==================== + + private void buildPendingInspectRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + // 批量查询物料 + Map itemMap = itemService.getItemMap( + convertSet(list, MesQcPendingInspectRespVO::getItemId)); + // 批量查询计量单位(通过物料的 unitMeasureId) + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 批量查询供应商(IQC 场景) + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesQcPendingInspectRespVO::getVendorId)); + // 批量查询客户(OQC/RQC 场景) + Map clientMap = clientService.getClientMap( + convertSet(list, MesQcPendingInspectRespVO::getClientId)); + // 批量查询工作站(IPQC/RQC 场景) + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesQcPendingInspectRespVO::getWorkstationId)); + // 批量查询任务(IPQC 场景) + Map taskMap = taskService.getTaskMap( + convertSet(list, MesQcPendingInspectRespVO::getTaskId)); + // 拼装 + list.forEach(vo -> { + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unit -> vo.setUnitName(unit.getName())); + }); + findAndThen(vendorMap, vo.getVendorId(), vendor -> vo.setVendorName(vendor.getName())); + findAndThen(clientMap, vo.getClientId(), client -> vo.setClientName(client.getName())); + findAndThen(workstationMap, vo.getWorkstationId(), + workstation -> vo.setWorkstationName(workstation.getName())); + findAndThen(taskMap, vo.getTaskId(), task -> vo.setTaskCode(task.getCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectPageReqVO.java new file mode 100644 index 000000000..7cfc63460 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 待检任务分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcPendingInspectPageReqVO extends PageParam { + + @Schema(description = "来源单据编号", example = "AN2025001") + private String sourceDocCode; + + @Schema(description = "检验类型", example = "1") + private Integer qcType; + + @Schema(description = "物料编号", example = "1024") + private Long itemId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java new file mode 100644 index 000000000..6e7f5c9a6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 待检任务 Response VO") +@Data +public class MesQcPendingInspectRespVO { + + @Schema(description = "来源单据 ID", example = "100") + private Long sourceDocId; + + @Schema(description = "来源单据类型(MesBizTypeConstants)", example = "100") + private Integer sourceDocType; + + @Schema(description = "来源单据编号", example = "AN2025001") + private String sourceDocCode; + + @Schema(description = "来源单据行 ID", example = "200") + private Long sourceLineId; + + @Schema(description = "检验类型(MesQcTypeEnum)", example = "1") + private Integer qcType; + + // ========== 物料 ========== + + @Schema(description = "物料 ID", example = "10") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + private String itemCode; + + @Schema(description = "物料名称", example = "物料A") + private String itemName; + + @Schema(description = "规格型号", example = "100mm*50mm") + private String specification; + + @Schema(description = "单位名称", example = "个") + private String unitName; + + // ========== 数量 ========== + + @Schema(description = "待检数量", example = "100.00") + private BigDecimal quantity; + + // ========== 供应商(IQC 场景) ========== + + @Schema(description = "供应商 ID", example = "5") + private Long vendorId; + + @Schema(description = "供应商名称", example = "供应商A") + private String vendorName; + + // ========== 工单/工作站/任务(IPQC/RQC 场景) ========== + + @Schema(description = "生产工单 ID", example = "10") + private Long workOrderId; + + @Schema(description = "工作站 ID", example = "20") + private Long workstationId; + + @Schema(description = "工作站名称", example = "工作站A") + private String workstationName; + + @Schema(description = "生产任务 ID", example = "30") + private Long taskId; + + @Schema(description = "生产任务编码", example = "TASK2025001") + private String taskCode; + + // ========== 客户(OQC/RQC 场景) ========== + + @Schema(description = "客户 ID", example = "40") + private Long clientId; + + @Schema(description = "客户名称", example = "客户A") + private String clientName; + + // ========== 时间 ========== + + @Schema(description = "记录时间") + private LocalDateTime recordTime; + +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/MesQcRqcController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/MesQcRqcController.java new file mode 100644 index 000000000..56f5c3537 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/MesQcRqcController.java @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.rqc; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.qc.rqc.vo.MesQcRqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.MesQcRqcRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.MesQcRqcSaveReqVO; +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.qc.rqc.MesQcRqcDO; +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.qc.rqc.MesQcRqcService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 退货检验单(RQC)") +@RestController +@RequestMapping("/mes/qc/rqc") +@Validated +public class MesQcRqcController { + + @Resource + private MesQcRqcService rqcService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建退货检验单") + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:create')") + public CommonResult createRqc(@Valid @RequestBody MesQcRqcSaveReqVO createReqVO) { + return success(rqcService.createRqc(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新退货检验单") + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:update')") + public CommonResult updateRqc(@Valid @RequestBody MesQcRqcSaveReqVO updateReqVO) { + rqcService.updateRqc(updateReqVO); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成退货检验单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:finish')") + public CommonResult finishRqc(@RequestParam("id") Long id) { + rqcService.finishRqc(id); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除退货检验单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:delete')") + public CommonResult deleteRqc(@RequestParam("id") Long id) { + rqcService.deleteRqc(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得退货检验单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:query')") + public CommonResult getRqc(@RequestParam("id") Long id) { + MesQcRqcDO rqc = rqcService.getRqc(id); + return success(buildRqcRespVOList(Collections.singletonList(rqc)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得退货检验单分页") + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:query')") + public CommonResult> getRqcPage(@Valid MesQcRqcPageReqVO pageReqVO) { + PageResult pageResult = rqcService.getRqcPage(pageReqVO); + return success(new PageResult<>(buildRqcRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出退货检验单 Excel") + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportRqcExcel(@Valid MesQcRqcPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = rqcService.getRqcPage(pageReqVO).getList(); + List voList = buildRqcRespVOList(list); + ExcelUtils.write(response, "退货检验单.xls", "数据", MesQcRqcRespVO.class, voList); + } + + // ==================== 拼接 VO ==================== + + private List buildRqcRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询物料 + Map itemMap = itemService.getItemMap( + convertSet(list, MesQcRqcDO::getItemId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 批量查询检测人员 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesQcRqcDO::getInspectorUserId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcRqcRespVO.class, vo -> { + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unit -> vo.setUnitName(unit.getName())); + }); + findAndThen(userMap, vo.getInspectorUserId(), + user -> vo.setInspectorNickname(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/MesQcRqcLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/MesQcRqcLineController.java new file mode 100644 index 000000000..2139ba585 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/MesQcRqcLineController.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.rqc; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.line.MesQcRqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.line.MesQcRqcLineRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 退货检验单行") +@RestController +@RequestMapping("/mes/qc/rqc/line") +@Validated +public class MesQcRqcLineController { + + @Resource + private MesQcRqcLineService rqcLineService; + @Resource + private MesQcIndicatorService indicatorService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @GetMapping("/get") + @Operation(summary = "获得退货检验单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:query')") + public CommonResult getRqcLine(@RequestParam("id") Long id) { + MesQcRqcLineDO line = rqcLineService.getRqcLine(id); + return success(buildLineRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得退货检验单行分页") + @PreAuthorize("@ss.hasPermission('mes:qc-rqc:query')") + public CommonResult> getRqcLinePage(@Valid MesQcRqcLinePageReqVO pageReqVO) { + PageResult pageResult = rqcLineService.getRqcLinePage(pageReqVO); + return success(new PageResult<>(buildLineRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildLineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询检测指标 + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(list, MesQcRqcLineDO::getIndicatorId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(list, MesQcRqcLineDO::getUnitMeasureId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcRqcLineRespVO.class, vo -> { + findAndThen(indicatorMap, vo.getIndicatorId(), indicator -> + vo.setIndicatorCode(indicator.getCode()).setIndicatorName(indicator.getName()) + .setIndicatorType(indicator.getType())); + findAndThen(unitMeasureMap, vo.getUnitMeasureId(), + unit -> vo.setUnitMeasureName(unit.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcPageReqVO.java new file mode 100644 index 000000000..b9566c169 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcPageReqVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 退货检验单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcRqcPageReqVO extends PageParam { + + @Schema(description = "检验单编号", example = "RQC2025") + private String code; + + @Schema(description = "来源单据类型", example = "1") + private Integer sourceDocType; + + @Schema(description = "来源单据编码", example = "RT2025") + private String sourceDocCode; + + @Schema(description = "产品物料 ID", example = "20") + private Long itemId; + + @Schema(description = "批次号", example = "BATCH001") + private String batchCode; + + @Schema(description = "检测结果", example = "1") + private Integer checkResult; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "检测人员用户 ID", example = "1") + private Long inspectorUserId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java new file mode 100644 index 000000000..df8d1bc98 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java @@ -0,0 +1,137 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 退货检验单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcRqcRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RQC20250101001") + @ExcelProperty("检验单编号") + private String code; + + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料A退货检验") + @ExcelProperty("检验单名称") + private String name; + + @Schema(description = "检验模板 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long templateId; + + // ========== 来源单据 ========== + + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + + @Schema(description = "来源单据类型", example = "116") + private Integer sourceDocType; + + @Schema(description = "来源单据行 ID", example = "300") + private Long sourceLineId; + + @Schema(description = "来源单据编码", example = "RT20250101001") + private String sourceDocCode; + + // ========== 检验类型 ========== + + @Schema(description = "检验类型", example = "1") + @ExcelProperty("检验类型") + private Integer type; + + // ========== 物料 ========== + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + private Long itemId; + + @Schema(description = "产品物料编码", example = "ITEM001") + @ExcelProperty("产品物料编码") + private String itemCode; + + @Schema(description = "产品物料名称", example = "物料A") + @ExcelProperty("产品物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "100mm*50mm") + private String itemSpecification; + + @Schema(description = "单位名称", example = "个") + private String unitName; + + @Schema(description = "批次号", example = "BATCH001") + @ExcelProperty("批次号") + private String batchCode; + + // ========== 数量 ========== + + @Schema(description = "检测数量", example = "100") + @ExcelProperty("检测数量") + private BigDecimal checkQuantity; + + @Schema(description = "合格品数量", example = "90") + @ExcelProperty("合格品数量") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不合格数量", example = "10") + @ExcelProperty("不合格数量") + private BigDecimal unqualifiedQuantity; + + // ========== 检验 ========== + + @Schema(description = "检测结果", example = "1") + @ExcelProperty("检测结果") + private Integer checkResult; + + @Schema(description = "检测日期") + @ExcelProperty("检测日期") + private LocalDateTime inspectDate; + + @Schema(description = "检测人员用户 ID", example = "1") + private Long inspectorUserId; + + @Schema(description = "检测人员昵称", example = "张三") + @ExcelProperty("检测人员") + private String inspectorNickname; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + // ========== 缺陷统计 ========== + + @Schema(description = "致命缺陷数量", example = "5") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "10") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "15") + private Integer minorQuantity; + + @Schema(description = "致命缺陷率(%)", example = "5.00") + private BigDecimal criticalRate; + + @Schema(description = "严重缺陷率(%)", example = "10.00") + private BigDecimal majorRate; + + @Schema(description = "轻微缺陷率(%)", example = "15.00") + private BigDecimal minorRate; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcSaveReqVO.java new file mode 100644 index 000000000..3b9fbf1d1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcSaveReqVO.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo; + +import cn.hutool.core.util.ObjUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 退货检验单新增/修改 Request VO") +@Data +public class MesQcRqcSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "检验单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RQC20250101001") + @NotEmpty(message = "检验单编号不能为空") + private String code; + + @Schema(description = "检验单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料A退货检验") + @NotEmpty(message = "检验单名称不能为空") + private String name; + + @Schema(description = "检验模板 ID", example = "100") + private Long templateId; + + // ========== 来源单据 ========== + + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + + @Schema(description = "来源单据类型", example = "116") + private Integer sourceDocType; + + @Schema(description = "来源单据行 ID", example = "300") + private Long sourceLineId; + + // ========== 检验类型 ========== + + @Schema(description = "检验类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检验类型不能为空") + private Integer type; + + // ========== 物料 ========== + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + @NotNull(message = "产品物料不能为空") + private Long itemId; + + @Schema(description = "批次号", example = "BATCH001") + private String batchCode; + + // ========== 数量 ========== + + @Schema(description = "检测数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "检测数量不能为空") + @DecimalMin(value = "0", message = "检测数量不能小于 0") + private BigDecimal checkQuantity; + + @Schema(description = "合格品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "90") + @NotNull(message = "合格品数量不能为空") + @DecimalMin(value = "0", message = "合格品数量不能小于 0") + private BigDecimal qualifiedQuantity; + + @Schema(description = "不合格数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "不合格数量不能为空") + @DecimalMin(value = "0", message = "不合格数量不能小于 0") + private BigDecimal unqualifiedQuantity; + + // ========== 检验 ========== + + @Schema(description = "检测结果", example = "1") + private Integer checkResult; + + @Schema(description = "检测日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "检测日期不能为空") + private LocalDateTime inspectDate; + + @Schema(description = "检测人员用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检测人员不能为空") + private Long inspectorUserId; + + @Schema(description = "备注", example = "备注") + private String remark; + + @AssertTrue(message = "检测数量必须等于合格品数量与不合格品数量之和") + @JsonIgnore + public boolean isQuantityValid() { + if (ObjUtil.hasNull(checkQuantity, qualifiedQuantity, unqualifiedQuantity)) { + return true; // @NotNull 会处理 null + } + return checkQuantity.compareTo(qualifiedQuantity.add(unqualifiedQuantity)) == 0; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLinePageReqVO.java new file mode 100644 index 000000000..f72361ccf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 退货检验行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcRqcLinePageReqVO extends PageParam { + + @Schema(description = "退货检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "退货检验单 ID 不能为空") + private Long rqcId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLineRespVO.java new file mode 100644 index 000000000..da3874772 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLineRespVO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 退货检验行 Response VO") +@Data +@Accessors(chain = true) +public class MesQcRqcLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "退货检验单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long rqcId; + + @Schema(description = "检测指标 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Long indicatorId; + + @Schema(description = "检测指标编码", example = "IND001") + private String indicatorCode; + + @Schema(description = "检测指标名称", example = "外观") + private String indicatorName; + + @Schema(description = "检测指标类型", example = "QUANTITATIVE") + private String indicatorType; + + @Schema(description = "检测工具", example = "卡尺") + private String tool; + + @Schema(description = "检测方法", example = "目测") + private String checkMethod; + + @Schema(description = "标准值", example = "10.5000") + private BigDecimal standardValue; + + @Schema(description = "计量单位 ID", example = "3") + private Long unitMeasureId; + + @Schema(description = "计量单位名称", example = "毫米") + private String unitMeasureName; + + @Schema(description = "误差上限", example = "11.0000") + private BigDecimal maxThreshold; + + @Schema(description = "误差下限", example = "10.0000") + private BigDecimal minThreshold; + + @Schema(description = "致命缺陷数量", example = "0") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "0") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "1") + private Integer minorQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateController.java new file mode 100644 index 000000000..735c9d3c6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateController.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.qc.template.vo.MesQcTemplatePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplateRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplateSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 质检方案") +@RestController +@RequestMapping("/mes/qc/template") +@Validated +public class MesQcTemplateController { + + @Resource + private MesQcTemplateService templateService; + + @PostMapping("/create") + @Operation(summary = "创建质检方案") + @PreAuthorize("@ss.hasPermission('mes:qc-template:create')") + public CommonResult createTemplate(@Valid @RequestBody MesQcTemplateSaveReqVO createReqVO) { + return success(templateService.createTemplate(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新质检方案") + @PreAuthorize("@ss.hasPermission('mes:qc-template:update')") + public CommonResult updateTemplate(@Valid @RequestBody MesQcTemplateSaveReqVO updateReqVO) { + templateService.updateTemplate(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除质检方案") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-template:delete')") + public CommonResult deleteTemplate(@RequestParam("id") Long id) { + templateService.deleteTemplate(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得质检方案") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-template:query')") + public CommonResult getTemplate(@RequestParam("id") Long id) { + MesQcTemplateDO template = templateService.getTemplate(id); + return success(BeanUtils.toBean(template, MesQcTemplateRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得质检方案分页") + @PreAuthorize("@ss.hasPermission('mes:qc-template:query')") + public CommonResult> getTemplatePage(@Valid MesQcTemplatePageReqVO pageReqVO) { + PageResult pageResult = templateService.getTemplatePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesQcTemplateRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得质检方案精简列表", description = "主要用于前端的下拉选项") + public CommonResult> getTemplateSimpleList() { + List list = templateService.getTemplateList(); + return success(BeanUtils.toBean(list, MesQcTemplateRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出质检方案 Excel") + @PreAuthorize("@ss.hasPermission('mes:qc-template:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTemplateExcel(@Valid MesQcTemplatePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = templateService.getTemplatePage(pageReqVO).getList(); + ExcelUtils.write(response, "质检方案.xls", "数据", MesQcTemplateRespVO.class, + BeanUtils.toBean(list, MesQcTemplateRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateIndicatorController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateIndicatorController.java new file mode 100644 index 000000000..0d2e7478b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateIndicatorController.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.MesQcTemplateIndicatorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.MesQcTemplateIndicatorRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.MesQcTemplateIndicatorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateIndicatorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 质检方案-检测指标项") +@RestController +@RequestMapping("/mes/qc/template/indicator") +@Validated +public class MesQcTemplateIndicatorController { + + @Resource + private MesQcTemplateIndicatorService templateIndicatorService; + @Resource + private MesQcIndicatorService indicatorService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建质检方案-检测指标项") + @PreAuthorize("@ss.hasPermission('mes:qc-template:create')") + public CommonResult createTemplateIndicator(@Valid @RequestBody MesQcTemplateIndicatorSaveReqVO createReqVO) { + return success(templateIndicatorService.createTemplateIndicator(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新质检方案-检测指标项") + @PreAuthorize("@ss.hasPermission('mes:qc-template:update')") + public CommonResult updateTemplateIndicator(@Valid @RequestBody MesQcTemplateIndicatorSaveReqVO updateReqVO) { + templateIndicatorService.updateTemplateIndicator(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除质检方案-检测指标项") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-template:update')") + public CommonResult deleteTemplateIndicator(@RequestParam("id") Long id) { + templateIndicatorService.deleteTemplateIndicator(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得质检方案-检测指标项") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-template:query')") + public CommonResult getTemplateIndicator(@RequestParam("id") Long id) { + MesQcTemplateIndicatorDO indicator = templateIndicatorService.getTemplateIndicator(id); + return success(buildIndicatorRespVOList(Collections.singletonList(indicator)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得质检方案-检测指标项分页") + @PreAuthorize("@ss.hasPermission('mes:qc-template:query')") + public CommonResult> getTemplateIndicatorPage( + @Valid MesQcTemplateIndicatorPageReqVO pageReqVO) { + PageResult pageResult = templateIndicatorService.getTemplateIndicatorPage(pageReqVO); + return success(new PageResult<>(buildIndicatorRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildIndicatorRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询质检指标 + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(list, MesQcTemplateIndicatorDO::getIndicatorId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(list, MesQcTemplateIndicatorDO::getUnitMeasureId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcTemplateIndicatorRespVO.class, vo -> { + findAndThen(indicatorMap, vo.getIndicatorId(), indicator -> + vo.setIndicatorCode(indicator.getCode()).setIndicatorName(indicator.getName()) + .setIndicatorType(indicator.getType()).setIndicatorTool(indicator.getTool())); + findAndThen(unitMeasureMap, vo.getUnitMeasureId(), + unit -> vo.setUnitMeasureName(unit.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateItemController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateItemController.java new file mode 100644 index 000000000..25289d2b8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateItemController.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item.MesQcTemplateItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item.MesQcTemplateItemRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item.MesQcTemplateItemSaveReqVO; +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.qc.template.MesQcTemplateItemDO; +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.qc.template.MesQcTemplateItemService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 质检方案-产品关联") +@RestController +@RequestMapping("/mes/qc/template/item") +@Validated +public class MesQcTemplateItemController { + + @Resource + private MesQcTemplateItemService templateItemService; + @Resource + private MesMdItemService mdItemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建质检方案-产品关联") + @PreAuthorize("@ss.hasPermission('mes:qc-template:create')") + public CommonResult createTemplateItem(@Valid @RequestBody MesQcTemplateItemSaveReqVO createReqVO) { + return success(templateItemService.createTemplateItem(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新质检方案-产品关联") + @PreAuthorize("@ss.hasPermission('mes:qc-template:update')") + public CommonResult updateTemplateItem(@Valid @RequestBody MesQcTemplateItemSaveReqVO updateReqVO) { + templateItemService.updateTemplateItem(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除质检方案-产品关联") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:qc-template:update')") + public CommonResult deleteTemplateItem(@RequestParam("id") Long id) { + templateItemService.deleteTemplateItem(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得质检方案-产品关联") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:qc-template:query')") + public CommonResult getTemplateItem(@RequestParam("id") Long id) { + MesQcTemplateItemDO item = templateItemService.getTemplateItem(id); + return success(buildItemRespVOList(Collections.singletonList(item)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得质检方案-产品关联分页") + @PreAuthorize("@ss.hasPermission('mes:qc-template:query')") + public CommonResult> getTemplateItemPage( + @Valid MesQcTemplateItemPageReqVO pageReqVO) { + PageResult pageResult = templateItemService.getTemplateItemPage(pageReqVO); + return success(new PageResult<>(buildItemRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildItemRespVOList(List list) { + if (list.isEmpty()) { + return Collections.emptyList(); + } + // 批量查询物料 + Map itemMap = mdItemService.getItemMap( + convertSet(list, MesQcTemplateItemDO::getItemId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 拼装 VO + return BeanUtils.toBean(list, MesQcTemplateItemRespVO.class, vo -> { + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unit -> vo.setUnitMeasureName(unit.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplatePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplatePageReqVO.java new file mode 100644 index 000000000..c3faafefd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplatePageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 质检方案分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcTemplatePageReqVO extends PageParam { + + @Schema(description = "方案编号", example = "QCT001") + private String code; + + @Schema(description = "方案名称", example = "出货检验") + private String name; + + @Schema(description = "检测种类", example = "1") + private Integer type; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateRespVO.java new file mode 100644 index 000000000..ea5932ca4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateRespVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - MES 质检方案 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcTemplateRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "QCT001") + @ExcelProperty("方案编号") + private String code; + + @Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "成品出货检验方案") + @ExcelProperty("方案名称") + private String name; + + @Schema(description = "检测种类", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 3]") + @ExcelProperty("检测种类") + private List types; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateSaveReqVO.java new file mode 100644 index 000000000..dea9e3244 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateSaveReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - MES 质检方案新增/修改 Request VO") +@Data +public class MesQcTemplateSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "方案编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "QCT001") + @NotEmpty(message = "方案编号不能为空") + private String code; + + @Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "成品出货检验方案") + @NotEmpty(message = "方案名称不能为空") + private String name; + + @Schema(description = "检测种类(1-IQC 2-IPQC 3-OQC 4-RQC,字典 mes_qc_type)", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 3]") + @NotNull(message = "检测种类不能为空") + @Size(min = 1, message = "检测种类至少选择一项") + private List types; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorPageReqVO.java new file mode 100644 index 000000000..87be92f9d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorPageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 质检方案-检测指标项分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcTemplateIndicatorPageReqVO extends PageParam { + + @Schema(description = "质检方案ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "质检方案ID不能为空") + private Long templateId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java new file mode 100644 index 000000000..67d38388f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 质检方案-检测指标项 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcTemplateIndicatorRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "质检方案ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long templateId; + + @Schema(description = "质检指标ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long indicatorId; + + @Schema(description = "检测方法", example = "目视检查外观") + @ExcelProperty("检测方法") + private String checkMethod; + + @Schema(description = "标准值", example = "10.0000") + @ExcelProperty("标准值") + private BigDecimal standardValue; + + @Schema(description = "计量单位ID", example = "1") + private Long unitMeasureId; + + @Schema(description = "误差上限", example = "10.5000") + @ExcelProperty("误差上限") + private BigDecimal thresholdMax; + + @Schema(description = "误差下限", example = "9.5000") + @ExcelProperty("误差下限") + private BigDecimal thresholdMin; + + @Schema(description = "说明图URL", example = "https://example.com/doc.png") + private String docUrl; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + // ========== JOIN mes_qc_indicator ========== + + @Schema(description = "检测项编码", example = "QI001") + @ExcelProperty("检测项编码") + private String indicatorCode; + + @Schema(description = "检测项名称", example = "长度") + @ExcelProperty("检测项名称") + private String indicatorName; + + @Schema(description = "检测项类型(字典 mes_index_type)", example = "SIZE") + @ExcelProperty("检测项类型") + private String indicatorType; + + @Schema(description = "检测工具", example = "卡尺") + @ExcelProperty("检测工具") + private String indicatorTool; + + // ========== JOIN mes_md_unit_measure ========== + + @Schema(description = "计量单位名称", example = "mm") + @ExcelProperty("单位") + private String unitMeasureName; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorSaveReqVO.java new file mode 100644 index 000000000..7563c7963 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 质检方案-检测指标项新增/修改 Request VO") +@Data +public class MesQcTemplateIndicatorSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "质检方案ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "质检方案ID不能为空") + private Long templateId; + + @Schema(description = "质检指标ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "质检指标不能为空") + private Long indicatorId; + + @Schema(description = "检测方法", example = "目视检查外观") + private String checkMethod; + + @Schema(description = "标准值", example = "10.0000") + private BigDecimal standardValue; + + @Schema(description = "计量单位ID", example = "1") + private Long unitMeasureId; + + @Schema(description = "误差上限", example = "10.5000") + private BigDecimal thresholdMax; + + @Schema(description = "误差下限", example = "9.5000") + private BigDecimal thresholdMin; + + @Schema(description = "说明图URL", example = "https://example.com/doc.png") + private String docUrl; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemPageReqVO.java new file mode 100644 index 000000000..0ef17e318 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemPageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 质检方案-产品关联分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesQcTemplateItemPageReqVO extends PageParam { + + @Schema(description = "质检方案ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "质检方案ID不能为空") + private Long templateId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemRespVO.java new file mode 100644 index 000000000..91d4b2f19 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemRespVO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 质检方案-产品关联 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesQcTemplateItemRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "质检方案ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long templateId; + + @Schema(description = "产品物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "最低检测数", example = "5") + @ExcelProperty("最低检测数") + private Integer quantityCheck; + + @Schema(description = "最大不合格数", example = "0") + @ExcelProperty("最大不合格数") + private Integer quantityUnqualified; + + @Schema(description = "最大致命缺陷率(%)", example = "0") + @ExcelProperty("致命缺陷率%") + private BigDecimal criticalRate; + + @Schema(description = "最大严重缺陷率(%)", example = "0") + @ExcelProperty("严重缺陷率%") + private BigDecimal majorRate; + + @Schema(description = "最大轻微缺陷率(%)", example = "100") + @ExcelProperty("轻微缺陷率%") + private BigDecimal minorRate; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + // ========== JOIN mes_md_item ========== + + @Schema(description = "物料编码", example = "ITEM001") + @ExcelProperty("物料编码") + private String itemCode; + + @Schema(description = "物料名称", example = "螺丝") + @ExcelProperty("物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "M3x10") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "计量单位名称", example = "个") + @ExcelProperty("计量单位") + private String unitMeasureName; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemSaveReqVO.java new file mode 100644 index 000000000..5d761fef6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemSaveReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 质检方案-产品关联新增/修改 Request VO") +@Data +public class MesQcTemplateItemSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "质检方案ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "质检方案ID不能为空") + private Long templateId; + + @Schema(description = "产品物料ID(关联 mes_md_item)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品物料ID不能为空") + private Long itemId; + + @Schema(description = "最低检测数", example = "5") + private Integer quantityCheck; + + @Schema(description = "最大不合格数", example = "0") + private Integer quantityUnqualified; + + @Schema(description = "最大致命缺陷率(%)", example = "0") + private BigDecimal criticalRate; + + @Schema(description = "最大严重缺陷率(%)", example = "0") + private BigDecimal majorRate; + + @Schema(description = "最大轻微缺陷率(%)", example = "100") + private BigDecimal minorRate; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/package-info.java new file mode 100644 index 000000000..96ab7f580 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/package-info.java @@ -0,0 +1,4 @@ +/** + * MES 工具管理(Tool Management):工具类型、工具台账,管理生产所需的刀具、模具、夹具等工装资源 + */ +package cn.iocoder.yudao.module.mes.controller.admin.tm; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/MesTmToolController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/MesTmToolController.java new file mode 100644 index 000000000..a00ed78e6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/MesTmToolController.java @@ -0,0 +1,137 @@ +package cn.iocoder.yudao.module.mes.controller.admin.tm.tool; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.tm.tool.vo.MesTmToolPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.MesTmToolRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.MesTmToolSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolTypeDO; +import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolService; +import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 工具台账") +@RestController +@RequestMapping("/mes/tm/tool") +@Validated +public class MesTmToolController { + + @Resource + private MesTmToolService toolService; + + @Resource + private MesTmToolTypeService toolTypeService; + + @PostMapping("/create") + @Operation(summary = "创建工具") + @PreAuthorize("@ss.hasPermission('mes:tm-tool:create')") + public CommonResult createTool(@Valid @RequestBody MesTmToolSaveReqVO createReqVO) { + return success(toolService.createTool(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工具") + @PreAuthorize("@ss.hasPermission('mes:tm-tool:update')") + public CommonResult updateTool(@Valid @RequestBody MesTmToolSaveReqVO updateReqVO) { + toolService.updateTool(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工具") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:tm-tool:delete')") + public CommonResult deleteTool(@RequestParam("id") Long id) { + toolService.deleteTool(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工具") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:tm-tool:query')") + public CommonResult getTool(@RequestParam("id") Long id) { + MesTmToolDO tool = toolService.getTool(id); + MesTmToolRespVO respVO = BeanUtils.toBean(tool, MesTmToolRespVO.class); + // 拼接工具类型名称 + if (respVO != null && respVO.getToolTypeId() != null) { + MesTmToolTypeDO toolType = toolTypeService.getToolType(respVO.getToolTypeId()); + if (toolType != null) { + respVO.setToolTypeName(toolType.getName()); + } + } + return success(respVO); + } + + @GetMapping("/page") + @Operation(summary = "获得工具分页") + @PreAuthorize("@ss.hasPermission('mes:tm-tool:query')") + public CommonResult> getToolPage(@Valid MesTmToolPageReqVO pageReqVO) { + PageResult pageResult = toolService.getToolPage(pageReqVO); + return success(new PageResult<>(buildToolRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出工具 Excel") + @PreAuthorize("@ss.hasPermission('mes:tm-tool:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportToolExcel(@Valid MesTmToolPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = toolService.getToolPage(pageReqVO).getList(); + List voList = buildToolRespVOList(list); + // 导出 Excel + ExcelUtils.write(response, "工具台账.xls", "数据", MesTmToolRespVO.class, voList); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得工具精简列表") + @PreAuthorize("@ss.hasPermission('mes:tm-tool:query')") + public CommonResult> getToolSimpleList() { + List list = toolService.getToolList(); + return success(BeanUtils.toBean(list, MesTmToolRespVO.class)); + } + + // ==================== 拼接 VO ==================== + + @SuppressWarnings("CodeBlock2Expr") + private List buildToolRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 批量获取工具类型信息 + Map toolTypeMap = toolTypeService.getToolTypeMap( + convertSet(list, MesTmToolDO::getToolTypeId)); + // 2. 拼接 VO + return BeanUtils.toBean(list, MesTmToolRespVO.class, vo -> { + MapUtils.findAndThen(toolTypeMap, vo.getToolTypeId(), + toolType -> vo.setToolTypeName(toolType.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/MesTmToolTypeController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/MesTmToolTypeController.java new file mode 100644 index 000000000..50312bea7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/MesTmToolTypeController.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.mes.controller.admin.tm.tool; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.tm.tool.vo.type.MesTmToolTypePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypeRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolTypeDO; +import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 工具类型") +@RestController +@RequestMapping("/mes/tm/tool-type") +@Validated +public class MesTmToolTypeController { + + @Resource + private MesTmToolTypeService toolTypeService; + + @PostMapping("/create") + @Operation(summary = "创建工具类型") + @PreAuthorize("@ss.hasPermission('mes:tm-tool-type:create')") + public CommonResult createToolType(@Valid @RequestBody MesTmToolTypeSaveReqVO createReqVO) { + return success(toolTypeService.createToolType(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新工具类型") + @PreAuthorize("@ss.hasPermission('mes:tm-tool-type:update')") + public CommonResult updateToolType(@Valid @RequestBody MesTmToolTypeSaveReqVO updateReqVO) { + toolTypeService.updateToolType(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除工具类型") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:tm-tool-type:delete')") + public CommonResult deleteToolType(@RequestParam("id") Long id) { + toolTypeService.deleteToolType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得工具类型") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:tm-tool-type:query')") + public CommonResult getToolType(@RequestParam("id") Long id) { + MesTmToolTypeDO toolType = toolTypeService.getToolType(id); + return success(BeanUtils.toBean(toolType, MesTmToolTypeRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得工具类型分页") + @PreAuthorize("@ss.hasPermission('mes:tm-tool-type:query')") + public CommonResult> getToolTypePage(@Valid MesTmToolTypePageReqVO pageReqVO) { + PageResult pageResult = toolTypeService.getToolTypePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesTmToolTypeRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得工具类型精简列表", description = "主要用于前端的下拉选项") + public CommonResult> getToolTypeSimpleList() { + List list = toolTypeService.getToolTypeList(); + return success(BeanUtils.toBean(list, MesTmToolTypeRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出工具类型 Excel") + @PreAuthorize("@ss.hasPermission('mes:tm-tool-type:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportToolTypeExcel(@Valid MesTmToolTypePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = toolTypeService.getToolTypePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "工具类型.xls", "数据", MesTmToolTypeRespVO.class, + BeanUtils.toBean(list, MesTmToolTypeRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolPageReqVO.java new file mode 100644 index 000000000..b51082ee2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 工具台账分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesTmToolPageReqVO extends PageParam { + + @Schema(description = "工具编码", example = "T-001") + private String code; + + @Schema(description = "工具名称", example = "铣刀") + private String name; + + @Schema(description = "工具类型编号", example = "100") + private Long toolTypeId; + + @Schema(description = "品牌", example = "三菱") + private String brand; + + @Schema(description = "型号规格", example = "M5-100") + private String spec; + + @Schema(description = "状态", example = "1") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java new file mode 100644 index 000000000..edbec15fa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工具台账 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesTmToolRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "工具编码", example = "T-001") + @ExcelProperty("工具编码") + private String code; + + @Schema(description = "工具名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "5mm 铣刀") + @ExcelProperty("工具名称") + private String name; + + @Schema(description = "品牌", example = "三菱") + @ExcelProperty("品牌") + private String brand; + + @Schema(description = "型号规格", example = "M5-100") + @ExcelProperty("型号规格") + private String spec; + + @Schema(description = "工具类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Long toolTypeId; + + @Schema(description = "工具类型名称", example = "铣刀") + @ExcelProperty("工具类型") + private String toolTypeName; + + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("数量") + private Integer quantity; + + @Schema(description = "可用数量", example = "1") + @ExcelProperty("可用数量") + private Integer availableQuantity; + + @Schema(description = "保养维护类型", example = "1") + @ExcelProperty(value = "保养维护类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_TM_MAINTEN_TYPE) + private Integer maintenType; + + @Schema(description = "下次保养周期(次数)", example = "100") + @ExcelProperty("下次保养周期") + private Integer nextMaintenPeriod; + + @Schema(description = "下次保养日期", example = "2024-06-01 00:00:00") + @ExcelProperty("下次保养日期") + private LocalDateTime nextMaintenDate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_TM_TOOL_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolSaveReqVO.java new file mode 100644 index 000000000..1ba1b3293 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolSaveReqVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工具台账新增/修改 Request VO") +@Data +public class MesTmToolSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "工具编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "T-001") + @NotEmpty(message = "工具编码不能为空") + private String code; + + @Schema(description = "工具名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "5mm 铣刀") + @NotEmpty(message = "工具名称不能为空") + private String name; + + @Schema(description = "品牌", example = "三菱") + private String brand; + + @Schema(description = "型号规格", example = "M5-100") + private String spec; + + @Schema(description = "工具类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "工具类型不能为空") + private Long toolTypeId; + + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "数量不能为空") + private Integer quantity; + + @Schema(description = "可用数量", example = "1") + private Integer availableQuantity; + + @Schema(description = "保养维护类型", example = "1") + private Integer maintenType; + + @Schema(description = "下次保养周期(次数)", example = "100") + private Integer nextMaintenPeriod; + + @Schema(description = "下次保养日期", example = "2024-06-01 00:00:00") + private LocalDateTime nextMaintenDate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypePageReqVO.java new file mode 100644 index 000000000..3ea64d1dc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypePageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 工具类型分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesTmToolTypePageReqVO extends PageParam { + + @Schema(description = "类型编码", example = "TT-001") + private String code; + + @Schema(description = "类型名称", example = "铣刀") + private String name; + + @Schema(description = "保养维护类型", example = "1") + private Integer maintenType; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeRespVO.java new file mode 100644 index 000000000..e46c4008a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 工具类型 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesTmToolTypeRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "TT-001") + @ExcelProperty("类型编码") + private String code; + + @Schema(description = "类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "铣刀") + @ExcelProperty("类型名称") + private String name; + + @Schema(description = "是否编码管理", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty("是否编码管理") + private Boolean codeFlag; + + @Schema(description = "保养维护类型", example = "1") + @ExcelProperty(value = "保养维护类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.MES_TM_MAINTEN_TYPE) + private Integer maintenType; + + @Schema(description = "保养周期", example = "30") + @ExcelProperty("保养周期") + private Integer maintenPeriod; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeSaveReqVO.java new file mode 100644 index 000000000..e331930f4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeSaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 工具类型新增/修改 Request VO") +@Data +public class MesTmToolTypeSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "TT-001") + @NotEmpty(message = "类型编码不能为空") + private String code; + + @Schema(description = "类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "铣刀") + @NotEmpty(message = "类型名称不能为空") + private String name; + + @Schema(description = "是否编码管理", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否编码管理不能为空") + private Boolean codeFlag; + + @Schema(description = "保养维护类型", example = "1") + private Integer maintenType; + + @Schema(description = "保养周期", example = "30") + private Integer maintenPeriod; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java new file mode 100644 index 000000000..cece976a4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.arrivalnotice.vo.MesWmArrivalNoticePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticeRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 到货通知单") +@RestController +@RequestMapping("/mes/wm/arrival-notice") +@Validated +public class MesWmArrivalNoticeController { + + @Resource + private MesWmArrivalNoticeService arrivalNoticeService; + + @Resource + private MesMdVendorService vendorService; + + @PostMapping("/create") + @Operation(summary = "创建到货通知单") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:create')") + public CommonResult createArrivalNotice(@Valid @RequestBody MesWmArrivalNoticeSaveReqVO createReqVO) { + return success(arrivalNoticeService.createArrivalNotice(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改到货通知单") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:update')") + public CommonResult updateArrivalNotice(@Valid @RequestBody MesWmArrivalNoticeSaveReqVO updateReqVO) { + arrivalNoticeService.updateArrivalNotice(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除到货通知单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:delete')") + public CommonResult deleteArrivalNotice(@RequestParam("id") Long id) { + arrivalNoticeService.deleteArrivalNotice(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得到货通知单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:query')") + public CommonResult getArrivalNotice(@RequestParam("id") Long id) { + MesWmArrivalNoticeDO notice = arrivalNoticeService.getArrivalNotice(id); + if (notice == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(notice)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得到货通知单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:query')") + public CommonResult> getArrivalNoticePage( + @Valid MesWmArrivalNoticePageReqVO pageReqVO) { + PageResult pageResult = arrivalNoticeService.getArrivalNoticePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出到货通知单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportArrivalNoticeExcel(@Valid MesWmArrivalNoticePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = arrivalNoticeService.getArrivalNoticePage(pageReqVO); + ExcelUtils.write(response, "到货通知单.xls", "数据", MesWmArrivalNoticeRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交到货通知单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:update')") + public CommonResult submitArrivalNotice(@RequestParam("id") Long id) { + arrivalNoticeService.submitArrivalNotice(id); + return success(true); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得到货通知单精简列表") + @Parameter(name = "status", description = "状态", example = "2") + public CommonResult> getArrivalNoticeSimpleList( + @RequestParam(value = "status", required = false) Integer status) { + List list = arrivalNoticeService.getArrivalNoticeListByStatus(status); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesWmArrivalNoticeDO::getVendorId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmArrivalNoticeRespVO.class, vo -> { + MapUtils.findAndThen(vendorMap, vo.getVendorId(), vendor -> + vo.setVendorCode(vendor.getCode()).setVendorName(vendor.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeLineController.java new file mode 100644 index 000000000..d0743a8c6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeLineController.java @@ -0,0 +1,132 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLineSaveReqVO; +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.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +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.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 到货通知单行") +@RestController +@RequestMapping("/mes/wm/arrival-notice-line") +@Validated +public class MesWmArrivalNoticeLineController { + + @Resource + private MesWmArrivalNoticeLineService arrivalNoticeLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesQcIqcService iqcService; + + @PostMapping("/create") + @Operation(summary = "创建到货通知单行") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:create')") + public CommonResult createArrivalNoticeLine(@Valid @RequestBody MesWmArrivalNoticeLineSaveReqVO createReqVO) { + return success(arrivalNoticeLineService.createArrivalNoticeLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改到货通知单行") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:update')") + public CommonResult updateArrivalNoticeLine(@Valid @RequestBody MesWmArrivalNoticeLineSaveReqVO updateReqVO) { + arrivalNoticeLineService.updateArrivalNoticeLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除到货通知单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:delete')") + public CommonResult deleteArrivalNoticeLine(@RequestParam("id") Long id) { + arrivalNoticeLineService.deleteArrivalNoticeLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得到货通知单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:query')") + public CommonResult getArrivalNoticeLine(@RequestParam("id") Long id) { + MesWmArrivalNoticeLineDO line = arrivalNoticeLineService.getArrivalNoticeLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得到货通知单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:query')") + public CommonResult> getArrivalNoticeLinePage( + @Valid MesWmArrivalNoticeLinePageReqVO pageReqVO) { + PageResult pageResult = arrivalNoticeLineService.getArrivalNoticeLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/list-by-notice-id") + @Operation(summary = "获得到货通知单行列表") + @Parameter(name = "noticeId", description = "到货通知单编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:query')") + public CommonResult> getArrivalNoticeLineListByNoticeId( + @RequestParam("noticeId") Long noticeId) { + List list = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(noticeId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmArrivalNoticeLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map iqcMap = iqcService.getIqcMap( + convertSet(list, MesWmArrivalNoticeLineDO::getIqcId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmArrivalNoticeLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(iqcMap, vo.getIqcId(), iqc -> vo.setIqcCode(iqc.getCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticePageReqVO.java new file mode 100644 index 000000000..90219affd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticePageReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 到货通知单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmArrivalNoticePageReqVO extends PageParam { + + @Schema(description = "通知单编码", example = "AN2026020001") + private String code; + + @Schema(description = "通知单名称", example = "钢板到货") + private String name; + + @Schema(description = "采购订单编号", example = "PO20260101") + private String purchaseOrderCode; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "到货日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] arrivalDate; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeRespVO.java new file mode 100644 index 000000000..10d1eab95 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeRespVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 到货通知单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmArrivalNoticeRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "通知单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "AN2026020001") + @ExcelProperty("通知单编码") + private String code; + + @Schema(description = "通知单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2 月份钢板到货") + @ExcelProperty("通知单名称") + private String name; + + @Schema(description = "采购订单编号", example = "PO20260101") + @ExcelProperty("采购订单编号") + private String purchaseOrderCode; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long vendorId; + + @Schema(description = "供应商编码", example = "V001") + @ExcelProperty("供应商编码") + private String vendorCode; + + @Schema(description = "供应商名称", example = "某供应商") + @ExcelProperty("供应商名称") + private String vendorName; + + @Schema(description = "到货日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("到货日期") + private LocalDateTime arrivalDate; + + @Schema(description = "联系人", example = "张三") + @ExcelProperty("联系人") + private String contactName; + + @Schema(description = "联系电话", example = "13800138000") + @ExcelProperty("联系电话") + private String contactTelephone; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeSaveReqVO.java new file mode 100644 index 000000000..32f8b4cae --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 到货通知单新增/修改 Request VO") +@Data +public class MesWmArrivalNoticeSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "通知单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "AN2026020001") + @NotEmpty(message = "通知单编码不能为空") + private String code; + + @Schema(description = "通知单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2 月份钢板到货") + @NotEmpty(message = "通知单名称不能为空") + private String name; + + @Schema(description = "采购订单编号", example = "PO20260101") + private String purchaseOrderCode; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "供应商编号不能为空") + private Long vendorId; + + @Schema(description = "到货日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "到货日期不能为空") + private LocalDateTime arrivalDate; + + @Schema(description = "联系人", example = "张三") + private String contactName; + + @Schema(description = "联系电话", example = "13800138000") + private String contactTelephone; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLinePageReqVO.java new file mode 100644 index 000000000..9c75f4039 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 到货通知单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmArrivalNoticeLinePageReqVO extends PageParam { + + @Schema(description = "到货通知单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "到货通知单编号不能为空") + private Long noticeId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLineRespVO.java new file mode 100644 index 000000000..d534bb2ca --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLineRespVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 到货通知单行 Response VO") +@Data +public class MesWmArrivalNoticeLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "到货通知单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long noticeId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "到货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00") + private BigDecimal arrivalQuantity; + + @Schema(description = "合格数量", example = "500.00") + private BigDecimal qualifiedQuantity; + + @Schema(description = "是否需要来料检验", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean iqcCheckFlag; + + @Schema(description = "来料检验单编号", example = "1") + private Long iqcId; + + @Schema(description = "来料检验单编码", example = "IQC20260201") + private String iqcCode; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLineSaveReqVO.java new file mode 100644 index 000000000..fee310648 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLineSaveReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 到货通知单行新增/修改 Request VO") +@Data +public class MesWmArrivalNoticeLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "到货通知单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "到货通知单编号不能为空") + private Long noticeId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "到货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00") + @NotNull(message = "到货数量不能为空") + @DecimalMin(value = "0.01", message = "到货数量必须大于 0") + private BigDecimal arrivalQuantity; + + @Schema(description = "是否需要来料检验", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否需要来料检验不能为空") + private Boolean iqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/MesWmBarcodeConfigController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/MesWmBarcodeConfigController.java new file mode 100644 index 000000000..4a12b4e67 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/MesWmBarcodeConfigController.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config.MesWmBarcodeConfigPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config.MesWmBarcodeConfigRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config.MesWmBarcodeConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeConfigDO; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeConfigService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 条码配置") +@RestController +@RequestMapping("/mes/wm/barcode-config") +@Validated +public class MesWmBarcodeConfigController { + + @Resource + private MesWmBarcodeConfigService barcodeConfigService; + + @PostMapping("/create") + @Operation(summary = "创建条码配置") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode-config:create')") + public CommonResult createBarcodeConfig(@Valid @RequestBody MesWmBarcodeConfigSaveReqVO createReqVO) { + return success(barcodeConfigService.createBarcodeConfig(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新条码配置") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode-config:update')") + public CommonResult updateBarcodeConfig(@Valid @RequestBody MesWmBarcodeConfigSaveReqVO updateReqVO) { + barcodeConfigService.updateBarcodeConfig(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除条码配置") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-barcode-config:delete')") + public CommonResult deleteBarcodeConfig(@RequestParam("id") Long id) { + barcodeConfigService.deleteBarcodeConfig(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得条码配置") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode-config:query')") + public CommonResult getBarcodeConfig(@RequestParam("id") Long id) { + MesWmBarcodeConfigDO config = barcodeConfigService.getBarcodeConfig(id); + return success(BeanUtils.toBean(config, MesWmBarcodeConfigRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得条码配置分页") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode-config:query')") + public CommonResult> getBarcodeConfigPage( + @Valid MesWmBarcodeConfigPageReqVO pageReqVO) { + PageResult pageResult = barcodeConfigService.getBarcodeConfigPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesWmBarcodeConfigRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/MesWmBarcodeController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/MesWmBarcodeController.java new file mode 100644 index 000000000..56a5f0932 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/MesWmBarcodeController.java @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.barcode.vo.MesWmBarcodePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodeRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeDO; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 条码清单") +@RestController +@RequestMapping("/mes/wm/barcode") +@Validated +public class MesWmBarcodeController { + + @Resource + private MesWmBarcodeService barcodeService; + + @PostMapping("/create") + @Operation(summary = "创建条码") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode:create')") + public CommonResult createBarcode(@Valid @RequestBody MesWmBarcodeSaveReqVO createReqVO) { + return success(barcodeService.createBarcode(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新条码") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode:update')") + public CommonResult updateBarcode(@Valid @RequestBody MesWmBarcodeSaveReqVO updateReqVO) { + barcodeService.updateBarcode(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除条码") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-barcode:delete')") + public CommonResult deleteBarcode(@RequestParam("id") Long id) { + barcodeService.deleteBarcode(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得条码") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode:query')") + public CommonResult getBarcode(@RequestParam("id") Long id) { + MesWmBarcodeDO barcode = barcodeService.getBarcode(id); + return success(BeanUtils.toBean(barcode, MesWmBarcodeRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得条码分页") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode:query')") + public CommonResult> getBarcodePage(@Valid MesWmBarcodePageReqVO pageReqVO) { + PageResult pageResult = barcodeService.getBarcodePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesWmBarcodeRespVO.class)); + } + + @GetMapping("/get-by-business") + @Operation(summary = "根据业务对象获取条码信息", description = "前端用于生成条码图片") + @Parameter(name = "bizType", description = "业务类型", required = true, example = "102") + @Parameter(name = "bizId", description = "业务编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode:query')") + public CommonResult getBarcodeByBusiness( + @RequestParam("bizType") Integer bizType, + @RequestParam("bizId") Long bizId) { + MesWmBarcodeDO barcode = barcodeService.getBarcodeByBizTypeAndBizId(bizType, bizId); + return success(BeanUtils.toBean(barcode, MesWmBarcodeRespVO.class)); + } + + @GetMapping("/generate-content") + @Operation(summary = "生成条码内容") + @Parameter(name = "bizType", description = "业务类型", required = true, example = "1") + @Parameter(name = "bizCode", description = "业务编码", required = true, example = "WO202403070001") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode:query')") + public CommonResult generateBarcodeContent(@RequestParam("bizType") @NotNull(message = "业务类型不能为空") Integer bizType, + @RequestParam("bizCode") @NotBlank(message = "业务编码不能为空") String bizCode) { + String content = barcodeService.generateBarcodeContent(bizType, bizCode); + return success(content); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出条码清单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-barcode:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportBarcodeExcel(@Valid MesWmBarcodePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = barcodeService.getBarcodePage(pageReqVO).getList(); + List voList = BeanUtils.toBean(list, MesWmBarcodeRespVO.class); + ExcelUtils.write(response, "条码清单.xls", "数据", MesWmBarcodeRespVO.class, voList); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodePageReqVO.java new file mode 100644 index 000000000..4ec96ea80 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodePageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 条码清单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmBarcodePageReqVO extends PageParam { + + @Schema(description = "条码配置编号", example = "1") + private Long configId; + + @Schema(description = "条码格式", example = "1") + private Integer format; + + @Schema(description = "业务类型", example = "102") + private Integer bizType; + + @Schema(description = "条码内容", example = "WH-WH001") + private String content; + + @Schema(description = "业务编号", example = "1024") + private Long bizId; + + @Schema(description = "业务编码", example = "WH001") + private String bizCode; + + @Schema(description = "业务名称", example = "原料仓") + private String bizName; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeRespVO.java new file mode 100644 index 000000000..5123e4589 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeRespVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 条码清单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmBarcodeRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "条码配置编号", example = "1") + private Long configId; + + @Schema(description = "条码格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("条码格式") + private Integer format; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "102") + @ExcelProperty("业务类型") + private Integer bizType; + + @Schema(description = "条码内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "WH-WH001") + @ExcelProperty("条码内容") + private String content; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long bizId; + + @Schema(description = "业务编码", example = "WH001") + @ExcelProperty("业务编码") + private String bizCode; + + @Schema(description = "业务名称", example = "原料仓") + @ExcelProperty("业务名称") + private String bizName; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeSaveReqVO.java new file mode 100644 index 000000000..0b548d0b6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeSaveReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 条码清单新增/修改 Request VO") +@Data +public class MesWmBarcodeSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "条码配置编号", example = "1") + private Long configId; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "102") + @NotNull(message = "业务类型不能为空") + private Integer bizType; + + @Schema(description = "条码内容", example = "WH-WH001") + private String content; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "业务编号不能为空") + private Long bizId; + + @Schema(description = "业务编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WH001") + @NotEmpty(message = "业务编码不能为空") + private String bizCode; + + @Schema(description = "业务名称", example = "原料仓") + private String bizName; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigPageReqVO.java new file mode 100644 index 000000000..903683b54 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 条码配置分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmBarcodeConfigPageReqVO extends PageParam { + + @Schema(description = "条码格式", example = "1") + private Integer format; + + @Schema(description = "业务类型", example = "102") + private Integer bizType; + + @Schema(description = "是否自动生成", example = "true") + private Boolean autoGenerateFlag; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigRespVO.java new file mode 100644 index 000000000..b6b97e5b4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigRespVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 条码配置 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmBarcodeConfigRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "条码格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("条码格式") + private Integer format; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "102") + @ExcelProperty("业务类型") + private Integer bizType; + + @Schema(description = "内容格式模板", requiredMode = Schema.RequiredMode.REQUIRED, example = "WH-{BUSINESSCODE}") + @ExcelProperty("内容格式模板") + private String contentFormat; + + @Schema(description = "内容样例", example = "WH-WH001") + @ExcelProperty("内容样例") + private String contentExample; + + @Schema(description = "是否自动生成", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty("是否自动生成") + private Boolean autoGenerateFlag; + + @Schema(description = "默认打印模板", example = "template1") + @ExcelProperty("默认打印模板") + private String defaultTemplate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigSaveReqVO.java new file mode 100644 index 000000000..fb0d319b6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigSaveReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 条码配置新增/修改 Request VO") +@Data +public class MesWmBarcodeConfigSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "条码格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "条码格式不能为空") + private Integer format; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "102") + @NotNull(message = "业务类型不能为空") + private Integer bizType; + + @Schema(description = "内容格式模板", requiredMode = Schema.RequiredMode.REQUIRED, example = "WH-{BUSINESSCODE}") + @NotEmpty(message = "内容格式模板不能为空") + private String contentFormat; + + @Schema(description = "内容样例", example = "WH-WH001") + private String contentExample; + + @Schema(description = "是否自动生成", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否自动生成不能为空") + private Boolean autoGenerateFlag; + + @Schema(description = "默认打印模板", example = "template1") + private String defaultTemplate; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java new file mode 100644 index 000000000..3e0134796 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/MesWmBatchController.java @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.batch; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +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.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +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.tm.tool.MesTmToolDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +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.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 批次管理") +@RestController +@RequestMapping("/mes/wm/batch") +@Validated +public class MesWmBatchController { + + @Resource + private MesWmBatchService batchService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesMdVendorService vendorService; + @Resource + private MesMdClientService clientService; + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesProTaskService taskService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesTmToolService toolService; + + @GetMapping("/get") + @Operation(summary = "获得批次详情") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-batch:query')") + public CommonResult getBatch(@RequestParam("id") Long id) { + MesWmBatchDO batch = batchService.getBatch(id); + return success(buildBatchRespVO(batch)); + } + + @GetMapping("/page") + @Operation(summary = "获得批次分页") + @PreAuthorize("@ss.hasPermission('mes:wm-batch:query')") + public CommonResult> getBatchPage(@Valid MesWmBatchPageReqVO pageReqVO) { + PageResult pageResult = batchService.getBatchPage(pageReqVO); + return success(new PageResult<>(buildBatchRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/forward-list") + @Operation(summary = "批次向前追溯") + @Parameter(name = "code", description = "批次编码", required = true, example = "BATCH20250314001") + @PreAuthorize("@ss.hasPermission('mes:wm-batch:query')") + public CommonResult> getForwardList(@RequestParam("code") @Valid String code) { + List list = batchService.getForwardBatchList(code); + return success(buildBatchRespVOList(list)); + } + + @GetMapping("/backward-list") + @Operation(summary = "批次向后追溯") + @Parameter(name = "code", description = "批次编码", required = true, example = "BATCH20250314001") + @PreAuthorize("@ss.hasPermission('mes:wm-batch:query')") + public CommonResult> getBackwardList(@RequestParam("code") @Valid String code) { + List list = batchService.getBackwardBatchList(code); + return success(buildBatchRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildBatchRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmBatchDO::getItemId)); + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesWmBatchDO::getVendorId)); + Map clientMap = clientService.getClientMap( + convertSet(list, MesWmBatchDO::getClientId)); + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesWmBatchDO::getWorkOrderId)); + Map taskMap = taskService.getTaskMap( + convertSet(list, MesWmBatchDO::getTaskId)); + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesWmBatchDO::getWorkstationId)); + Map toolMap = toolService.getToolMap( + convertSet(list, MesWmBatchDO::getToolId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmBatchRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()) + .setItemSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitName(unitMeasure.getName())); + }); + MapUtils.findAndThen(vendorMap, vo.getVendorId(), + vendor -> vo.setVendorCode(vendor.getCode()).setVendorName(vendor.getName())); + MapUtils.findAndThen(clientMap, vo.getClientId(), + client -> vo.setClientCode(client.getCode()).setClientName(client.getName())); + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), + workOrder -> vo.setWorkOrderCode(workOrder.getCode())); + MapUtils.findAndThen(taskMap, vo.getTaskId(), + task -> vo.setTaskCode(task.getCode())); + MapUtils.findAndThen(workstationMap, vo.getWorkstationId(), + workstation -> vo.setWorkstationCode(workstation.getCode())); + MapUtils.findAndThen(toolMap, vo.getToolId(), + tool -> vo.setToolCode(tool.getCode())); + }); + } + + private MesWmBatchRespVO buildBatchRespVO(MesWmBatchDO batch) { + if (batch == null) { + return null; + } + return buildBatchRespVOList(Collections.singletonList(batch)).get(0); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchGenerateReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchGenerateReqVO.java new file mode 100644 index 000000000..68af0183f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchGenerateReqVO.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo; + +import lombok.Data; + +import jakarta.validation.constraints.NotNull; +import java.time.LocalDateTime; + +/** + * 批次生成请求 VO + * + * @author 芋道源码 + */ +@Data +public class MesWmBatchGenerateReqVO { + + /** + * 物料ID + */ + @NotNull(message = "物料 ID 不能为空") + private Long itemId; + + /** + * 生产日期 + */ + private LocalDateTime produceDate; + /** + * 有效期 + */ + private LocalDateTime expireDate; + /** + * 入库日期 + */ + private LocalDateTime receiptDate; + + /** + * 供应商 ID + */ + private Long vendorId; + /** + * 客户 ID + */ + private Long clientId; + + /** + * 采购订单编号 + */ + private String purchaseOrderCode; + /** + * 销售订单编号 + */ + private String salesOrderCode; + + /** + * 生产工单 ID + */ + private Long workOrderId; + /** + * 生产任务 ID + */ + private Long taskId; + /** + * 工作站 ID + */ + private Long workstationId; + /** + * 工具 ID + */ + private Long toolId; + /** + * 模具 ID + */ + private Long moldId; + + /** + * 生产批号 + */ + private String lotNumber; + /** + * 质量状态 + */ + private Integer qualityStatus; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchPageReqVO.java new file mode 100644 index 000000000..9910c3819 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchPageReqVO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 批次管理分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmBatchPageReqVO extends PageParam { + + @Schema(description = "批次编码", example = "BATCH20250314001") + private String code; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "客户编号", example = "1") + private Long clientId; + + @Schema(description = "销售订单编号", example = "SO20250314001") + private String salesOrderCode; + + @Schema(description = "采购订单编号", example = "PO20250314001") + private String purchaseOrderCode; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "生产任务编号", example = "1") + private Long taskId; + + @Schema(description = "工作站编号", example = "1") + private Long workstationId; + + @Schema(description = "工具编号", example = "1") + private Long toolId; + + @Schema(description = "模具编号", example = "1") + private Long moldId; + + @Schema(description = "生产批号", example = "LOT20250314001") + private String lotNumber; + + @Schema(description = "质量状态", example = "1") + private Integer qualityStatus; + + @Schema(description = "生产日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] produceDate; + + @Schema(description = "有效期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] expireDate; + + @Schema(description = "入库日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] receiptDate; + +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchRespVO.java new file mode 100644 index 000000000..ee225e9ea --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/batch/vo/MesWmBatchRespVO.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 批次管理 Response VO") +@Data +public class MesWmBatchRespVO { + + @Schema(description = "批次 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "批次编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "BATCH20250314001") + private String code; + + @Schema(description = "物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + private String itemCode; + + @Schema(description = "物料名称", example = "产品A") + private String itemName; + + @Schema(description = "规格型号", example = "100*200") + private String itemSpecification; + + @Schema(description = "单位名称", example = "个") + private String unitName; + + @Schema(description = "生产日期") + private LocalDateTime produceDate; + + @Schema(description = "有效期") + private LocalDateTime expireDate; + + @Schema(description = "入库日期") + private LocalDateTime receiptDate; + + @Schema(description = "供应商 ID", example = "1") + private Long vendorId; + + @Schema(description = "供应商编码", example = "V001") + private String vendorCode; + + @Schema(description = "供应商名称", example = "供应商A") + private String vendorName; + + @Schema(description = "客户 ID", example = "1") + private Long clientId; + + @Schema(description = "客户编码", example = "C001") + private String clientCode; + + @Schema(description = "客户名称", example = "客户A") + private String clientName; + + @Schema(description = "采购订单编号", example = "PO20250314001") + private String purchaseOrderCode; + + @Schema(description = "销售订单编号", example = "SO20250314001") + private String salesOrderCode; + + @Schema(description = "生产工单 ID", example = "1") + private Long workOrderId; + + @Schema(description = "生产工单编号", example = "WO20250314001") + private String workOrderCode; + + @Schema(description = "生产任务 ID", example = "1") + private Long taskId; + + @Schema(description = "生产任务编号", example = "TASK20250314001") + private String taskCode; + + @Schema(description = "工作站 ID", example = "1") + private Long workstationId; + + @Schema(description = "工作站编码", example = "WS001") + private String workstationCode; + + @Schema(description = "工具 ID", example = "1") + private Long toolId; + + @Schema(description = "工具编号", example = "TOOL001") + private String toolCode; + + @Schema(description = "模具 ID", example = "1") + private Long moldId; + + @Schema(description = "生产批号", example = "LOT20250314001") + private String lotNumber; + + @Schema(description = "质量状态", example = "1") + private Integer qualityStatus; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/MesWmItemConsumeLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/MesWmItemConsumeLineController.java new file mode 100644 index 000000000..edeb6140d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/MesWmItemConsumeLineController.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume.vo.MesWmItemConsumeLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume.vo.MesWmItemConsumeLineRespVO; +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.wm.itemconsume.MesWmItemConsumeLineDO; +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.wm.itemconsume.MesWmItemConsumeLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 物料消耗记录行") +@RestController +@RequestMapping("/mes/wm/item-consume-line") +@Validated +public class MesWmItemConsumeLineController { + + @Resource + private MesWmItemConsumeLineService itemConsumeLineService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @GetMapping("/page") + @Operation(summary = "根据报工编号分页获取消耗行列表") + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:query')") + public CommonResult> getItemConsumeLinePage( + @Valid MesWmItemConsumeLinePageReqVO pageReqVO) { + // 1. 分页查询消耗行 + PageResult pageResult = + itemConsumeLineService.getItemConsumeLinePage(pageReqVO); + PageResult voPage = BeanUtils.toBean(pageResult, MesWmItemConsumeLineRespVO.class); + // 2. 拼接物料信息 + Map itemMap = itemService.getItemMap( + convertSet(pageResult.getList(), MesWmItemConsumeLineDO::getItemId)); + Map unitMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + for (MesWmItemConsumeLineRespVO vo : voPage.getList()) { + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + findAndThen(unitMap, item.getUnitMeasureId(), unit -> vo.setUnitName(unit.getName())); + }); + } + return success(voPage); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLinePageReqVO.java new file mode 100644 index 000000000..7cfdbdac8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLinePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 物料消耗记录行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmItemConsumeLinePageReqVO extends PageParam { + + @Schema(description = "报工记录编号", requiredMode = Schema.RequiredMode.REQUIRED) + private Long feedbackId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLineRespVO.java new file mode 100644 index 000000000..52c911d60 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLineRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 物料消耗记录行 Response VO") +@Data +public class MesWmItemConsumeLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "消耗记录编号", requiredMode = Schema.RequiredMode.REQUIRED) + private Long consumeId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED) + private Long itemId; + + @Schema(description = "消耗数量", requiredMode = Schema.RequiredMode.REQUIRED) + private BigDecimal quantity; + + @Schema(description = "批次编号") + private Long batchId; + + @Schema(description = "批次号") + private String batchCode; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + // ==================== 关联信息 ==================== + + @Schema(description = "物资编码") + private String itemCode; + + @Schema(description = "物资名称") + private String itemName; + + @Schema(description = "规格型号") + private String specification; + + @Schema(description = "单位") + private String unitName; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptController.java new file mode 100644 index 000000000..692c84767 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptController.java @@ -0,0 +1,176 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.itemreceipt.vo.MesWmItemReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import cn.iocoder.yudao.module.mes.service.wm.itemreceipt.MesWmItemReceiptService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 采购入库单") +@RestController +@RequestMapping("/mes/wm/item-receipt") +@Validated +public class MesWmItemReceiptController { + + @Resource + private MesWmItemReceiptService itemReceiptService; + + @Resource + private MesMdVendorService vendorService; + + @Resource + private MesQcIqcService iqcService; + + @Resource + private MesWmArrivalNoticeService arrivalNoticeService; + + @PostMapping("/create") + @Operation(summary = "创建采购入库单") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:create')") + public CommonResult createItemReceipt(@Valid @RequestBody MesWmItemReceiptSaveReqVO createReqVO) { + return success(itemReceiptService.createItemReceipt(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改采购入库单") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:update')") + public CommonResult updateItemReceipt(@Valid @RequestBody MesWmItemReceiptSaveReqVO updateReqVO) { + itemReceiptService.updateItemReceipt(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:delete')") + public CommonResult deleteItemReceipt(@RequestParam("id") Long id) { + itemReceiptService.deleteItemReceipt(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购入库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:query')") + public CommonResult getItemReceipt(@RequestParam("id") Long id) { + MesWmItemReceiptDO receipt = itemReceiptService.getItemReceipt(id); + if (receipt == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(receipt)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得采购入库单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:query')") + public CommonResult> getItemReceiptPage( + @Valid MesWmItemReceiptPageReqVO pageReqVO) { + PageResult pageResult = itemReceiptService.getItemReceiptPage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出采购入库单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportItemReceiptExcel(@Valid MesWmItemReceiptPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = itemReceiptService.getItemReceiptPage(pageReqVO); + ExcelUtils.write(response, "采购入库单.xls", "数据", MesWmItemReceiptRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交采购入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:update')") + public CommonResult submitItemReceipt(@RequestParam("id") Long id) { + itemReceiptService.submitItemReceipt(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "执行上架") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:update')") + public CommonResult stockItemReceipt(@RequestParam("id") Long id) { + itemReceiptService.stockItemReceipt(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "执行入库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:finish')") + public CommonResult finishItemReceipt(@RequestParam("id") Long id) { + itemReceiptService.finishItemReceipt(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消采购入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:update')") + public CommonResult cancelItemReceipt(@RequestParam("id") Long id) { + itemReceiptService.cancelItemReceipt(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesWmItemReceiptDO::getVendorId)); + Map iqcMap = iqcService.getIqcMap( + convertSet(list, MesWmItemReceiptDO::getIqcId)); + Map noticeMap = arrivalNoticeService.getArrivalNoticeMap( + convertSet(list, MesWmItemReceiptDO::getNoticeId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmItemReceiptRespVO.class, vo -> { + MapUtils.findAndThen(vendorMap, vo.getVendorId(), + vendor -> vo.setVendorName(vendor.getName())); + MapUtils.findAndThen(iqcMap, vo.getIqcId(), + iqc -> vo.setIqcCode(iqc.getCode())); + MapUtils.findAndThen(noticeMap, vo.getNoticeId(), notice -> + vo.setNoticeCode(notice.getCode()).setPurchaseOrderCode(notice.getPurchaseOrderCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptDetailController.java new file mode 100644 index 000000000..5cf0afbe0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptDetailController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailSaveReqVO; +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.wm.itemreceipt.MesWmItemReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.itemreceipt.MesWmItemReceiptDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 采购入库明细") +@RestController +@RequestMapping("/mes/wm/item-receipt-detail") +@Validated +public class MesWmItemReceiptDetailController { + + @Resource + private MesWmItemReceiptDetailService itemReceiptDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建采购入库明细") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:create')") + public CommonResult createItemReceiptDetail(@Valid @RequestBody MesWmItemReceiptDetailSaveReqVO createReqVO) { + return success(itemReceiptDetailService.createItemReceiptDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改采购入库明细") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:update')") + public CommonResult updateItemReceiptDetail(@Valid @RequestBody MesWmItemReceiptDetailSaveReqVO updateReqVO) { + itemReceiptDetailService.updateItemReceiptDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购入库明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:delete')") + public CommonResult deleteItemReceiptDetail(@RequestParam("id") Long id) { + itemReceiptDetailService.deleteItemReceiptDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购入库明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:query')") + public CommonResult getItemReceiptDetail(@RequestParam("id") Long id) { + MesWmItemReceiptDetailDO detail = itemReceiptDetailService.getItemReceiptDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得采购入库明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:query')") + public CommonResult> getItemReceiptDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = itemReceiptDetailService.getItemReceiptDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmItemReceiptDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmItemReceiptDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmItemReceiptDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmItemReceiptDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmItemReceiptDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java new file mode 100644 index 000000000..7d7307bd3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLineSaveReqVO; +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.wm.itemreceipt.MesWmItemReceiptLineDO; +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.wm.itemreceipt.MesWmItemReceiptLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 采购入库单行") +@RestController +@RequestMapping("/mes/wm/item-receipt-line") +@Validated +public class MesWmItemReceiptLineController { + + @Resource + private MesWmItemReceiptLineService itemReceiptLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建采购入库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:create')") + public CommonResult createItemReceiptLine(@Valid @RequestBody MesWmItemReceiptLineSaveReqVO createReqVO) { + return success(itemReceiptLineService.createItemReceiptLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改采购入库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:update')") + public CommonResult updateItemReceiptLine(@Valid @RequestBody MesWmItemReceiptLineSaveReqVO updateReqVO) { + itemReceiptLineService.updateItemReceiptLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购入库单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:delete')") + public CommonResult deleteItemReceiptLine(@RequestParam("id") Long id) { + itemReceiptLineService.deleteItemReceiptLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购入库单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:query')") + public CommonResult getItemReceiptLine(@RequestParam("id") Long id) { + MesWmItemReceiptLineDO line = itemReceiptLineService.getItemReceiptLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得采购入库单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-item-receipt:query')") + public CommonResult> getItemReceiptLinePage( + @Valid MesWmItemReceiptLinePageReqVO pageReqVO) { + PageResult pageResult = itemReceiptLineService.getItemReceiptLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmItemReceiptLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmItemReceiptLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptPageReqVO.java new file mode 100644 index 000000000..0f7ae53e5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 采购入库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmItemReceiptPageReqVO extends PageParam { + + @Schema(description = "入库单编码", example = "IR2026020001") + private String code; + + @Schema(description = "入库单名称", example = "钢板入库单") + private String name; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "入库日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] receiptDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptRespVO.java new file mode 100644 index 000000000..da430a77a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptRespVO.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 采购入库单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmItemReceiptRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "入库单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "IR2026020001") + @ExcelProperty("入库单编码") + private String code; + + @Schema(description = "入库单名称", example = "钢板入库单") + @ExcelProperty("入库单名称") + private String name; + + @Schema(description = "来料检验单编号", example = "1") + private Long iqcId; + + @Schema(description = "来料检验单编码", example = "IQC20260201") + @ExcelProperty("来料检验单") + private String iqcCode; + + @Schema(description = "到货通知单编号", example = "1") + private Long noticeId; + + @Schema(description = "到货通知单编码", example = "AN2026020001") + @ExcelProperty("到货通知单") + private String noticeCode; + + @Schema(description = "采购订单号", example = "PO20260201") + @ExcelProperty("采购订单号") + private String purchaseOrderCode; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "供应商名称", example = "某供应商") + @ExcelProperty("供应商") + private String vendorName; + + @Schema(description = "入库日期") + @ExcelProperty("入库日期") + private LocalDateTime receiptDate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptSaveReqVO.java new file mode 100644 index 000000000..07cee3e46 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 采购入库单新增/修改 Request VO") +@Data +public class MesWmItemReceiptSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "IR2026020001") + @NotEmpty(message = "入库单编码不能为空") + private String code; + + @Schema(description = "入库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "钢板入库单") + @NotEmpty(message = "入库单名称不能为空") + private String name; + + @Schema(description = "来料检验单编号", example = "1") + private Long iqcId; + + @Schema(description = "到货通知单编号", example = "1") + private Long noticeId; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "供应商不能为空") + private Long vendorId; + + @Schema(description = "入库日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "入库日期不能为空") + private LocalDateTime receiptDate; + + @Schema(description = "采购订单号", example = "PO20260201") + private String purchaseOrderCode; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailPageReqVO.java new file mode 100644 index 000000000..360bcf969 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 采购入库明细分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmItemReceiptDetailPageReqVO extends PageParam { + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单编号不能为空") + private Long receiptId; + + @Schema(description = "入库单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单行编号不能为空") + private Long lineId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailRespVO.java new file mode 100644 index 000000000..b8f9ee6ad --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailRespVO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 采购入库明细 Response VO") +@Data +public class MesWmItemReceiptDetailRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "入库单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long lineId; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "上架数量", example = "300.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原料仓") + private String warehouseName; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A 区") + private String locationName; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A-01") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailSaveReqVO.java new file mode 100644 index 000000000..e2354e033 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailSaveReqVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 采购入库明细新增/修改 Request VO") +@Data +public class MesWmItemReceiptDetailSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单行编号不能为空") + private Long lineId; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单编号不能为空") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "上架数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") + @NotNull(message = "上架数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "上架数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLinePageReqVO.java new file mode 100644 index 000000000..d8e8ef416 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLinePageReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +@Schema(description = "管理后台 - MES 采购入库单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmItemReceiptLinePageReqVO extends PageParam { + + @Schema(description = "入库单编号", example = "1") + private Long receiptId; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "入库单编号列表(内部使用,供应商过滤时自动填充)", hidden = true) + private List receiptIds; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java new file mode 100644 index 000000000..25596dbdc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 采购入库单行 Response VO") +@Data +public class MesWmItemReceiptLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long receiptId; + + @Schema(description = "到货通知单行编号", example = "1") + private Long arrivalNoticeLineId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "入库数量", example = "500.00") + private BigDecimal receivedQuantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "BATCH20260110") + private String batchCode; + + @Schema(description = "生产日期") + private LocalDateTime productionDate; + + @Schema(description = "有效期") + private LocalDateTime expireDate; + + @Schema(description = "生产批号", example = "PB20260110") + private String lotNumber; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java new file mode 100644 index 000000000..00f656bb2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 采购入库单行新增/修改 Request VO") +@Data +public class MesWmItemReceiptLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单编号不能为空") + private Long receiptId; + + @Schema(description = "到货通知单行编号", example = "1") + private Long arrivalNoticeLineId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00") + @NotNull(message = "入库数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "入库数量必须大于 0") + private BigDecimal receivedQuantity; + + @Schema(description = "生产日期") + private LocalDateTime productionDate; + + @Schema(description = "有效期") + private LocalDateTime expireDate; + + @Schema(description = "生产批号", example = "PB20260110") + private String lotNumber; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java new file mode 100644 index 000000000..bd40c070a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java @@ -0,0 +1,153 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.materialstock.vo.MesWmMaterialStockPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockFreezeReqVO; +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.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 库存台账") +@RestController +@RequestMapping("/mes/wm/material-stock") +@Validated +public class MesWmMaterialStockController { + + @Resource + private MesWmMaterialStockService materialStockService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @Resource + private MesMdVendorService vendorService; + + @GetMapping("/get") + @Operation(summary = "获得库存记录") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-material-stock:query')") + public CommonResult getMaterialStock(@RequestParam("id") Long id) { + MesWmMaterialStockDO stock = materialStockService.getMaterialStock(id); + if (stock == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(stock)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得库存台账分页") + @PreAuthorize("@ss.hasPermission('mes:wm-material-stock:query')") + public CommonResult> getMaterialStockPage( + @Valid MesWmMaterialStockPageReqVO pageReqVO) { + PageResult pageResult = materialStockService.getMaterialStockPage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @PutMapping("/update-frozen") + @Operation(summary = "更新库存冻结状态") + @PreAuthorize("@ss.hasPermission('mes:wm-material-stock:update')") + public CommonResult updateMaterialStockFrozen( + @Valid @RequestBody MesWmMaterialStockFreezeReqVO updateReqVO) { + materialStockService.updateMaterialStockFrozen(updateReqVO); + return success(true); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出库存台账 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-material-stock:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportMaterialStockExcel(@Valid MesWmMaterialStockPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = materialStockService.getMaterialStockPage(pageReqVO); + ExcelUtils.write(response, "库存台账.xls", "数据", MesWmMaterialStockRespVO.class, + buildRespVOList(pageResult.getList())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmMaterialStockDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmMaterialStockDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmMaterialStockDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmMaterialStockDO::getAreaId)); + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesWmMaterialStockDO::getVendorId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmMaterialStockRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + MapUtils.findAndThen(vendorMap, vo.getVendorId(), + vendor -> vo.setVendorName(vendor.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockFreezeReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockFreezeReqVO.java new file mode 100644 index 000000000..d48a0b67e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockFreezeReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 库存台账冻结/解冻 Request VO") +@Data +public class MesWmMaterialStockFreezeReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "编号不能为空") + private Long id; + + @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "冻结状态不能为空") + private Boolean frozen; + +} + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockListReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockListReqVO.java new file mode 100644 index 000000000..cf8d062f3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockListReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 物料库存查询 Request VO") +@Data +public class MesWmMaterialStockListReqVO { + + @Schema(description = "仓库编号") + private Long warehouseId; + + @Schema(description = "库区编号") + private Long locationId; + + @Schema(description = "库位编号") + private Long areaId; + + @Schema(description = "物料编号") + private Long itemId; + + @Schema(description = "批次编号") + private Long batchId; + + @Schema(description = "批次号") + private String batchCode; + + @Schema(description = "开始时间(动态盘点用)") + private LocalDateTime startTime; + + @Schema(description = "结束时间(动态盘点用)") + private LocalDateTime endTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockPageReqVO.java new file mode 100644 index 000000000..0a880e230 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockPageReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 库存台账分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmMaterialStockPageReqVO extends PageParam { + + @Schema(description = "物料分类编号", example = "1") + private Long itemTypeId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "批次号", example = "B20260101") + private String batchCode; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "是否冻结", example = "false") + private Boolean frozen; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java new file mode 100644 index 000000000..366e64f9b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 库存台账 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmMaterialStockRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "物料分类编号", example = "1") + private Long itemTypeId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + @ExcelProperty("物料编码") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + @ExcelProperty("物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + @ExcelProperty("计量单位") + private String unitMeasureName; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "B20260101") + @ExcelProperty("批次号") + private String batchCode; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原料仓") + @ExcelProperty("仓库") + private String warehouseName; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A 区") + @ExcelProperty("库区") + private String locationName; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A-01") + @ExcelProperty("库位") + private String areaName; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "供应商名称", example = "某供应商") + @ExcelProperty("供应商") + private String vendorName; + + @Schema(description = "在库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.0000") + @ExcelProperty("在库数量") + private BigDecimal quantity; + + @Schema(description = "入库时间") + @ExcelProperty("入库时间") + private LocalDateTime receiptTime; + + @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @ExcelProperty("是否冻结") + private Boolean frozen; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueController.java new file mode 100644 index 000000000..0008b065b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueController.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.miscissue.vo.MesWmMiscIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssueRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDO; +import cn.iocoder.yudao.module.mes.service.wm.miscissue.MesWmMiscIssueService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 杂项出库单") +@RestController +@RequestMapping("/mes/wm/misc-issue") +@Validated +public class MesWmMiscIssueController { + + @Resource + private MesWmMiscIssueService miscIssueService; + + @PostMapping("/create") + @Operation(summary = "创建杂项出库单") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:create')") + public CommonResult createMiscIssue(@Valid @RequestBody MesWmMiscIssueSaveReqVO createReqVO) { + return success(miscIssueService.createMiscIssue(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改杂项出库单") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:update')") + public CommonResult updateMiscIssue(@Valid @RequestBody MesWmMiscIssueSaveReqVO updateReqVO) { + miscIssueService.updateMiscIssue(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除杂项出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:delete')") + public CommonResult deleteMiscIssue(@RequestParam("id") Long id) { + miscIssueService.deleteMiscIssue(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得杂项出库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:query')") + public CommonResult getMiscIssue(@RequestParam("id") Long id) { + MesWmMiscIssueDO issue = miscIssueService.getMiscIssue(id); + if (issue == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(issue)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得杂项出库单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:query')") + public CommonResult> getMiscIssuePage( + @Valid MesWmMiscIssuePageReqVO pageReqVO) { + PageResult pageResult = miscIssueService.getMiscIssuePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出杂项出库单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportMiscIssueExcel(@Valid MesWmMiscIssuePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = miscIssueService.getMiscIssuePage(pageReqVO); + ExcelUtils.write(response, "杂项出库单.xls", "数据", MesWmMiscIssueRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交杂项出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:update')") + public CommonResult submitMiscIssue(@RequestParam("id") Long id) { + miscIssueService.submitMiscIssue(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "执行出库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:finish')") + public CommonResult finishMiscIssue(@RequestParam("id") Long id) { + miscIssueService.finishMiscIssue(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消杂项出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:update')") + public CommonResult cancelMiscIssue(@RequestParam("id") Long id) { + miscIssueService.cancelMiscIssue(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + return BeanUtils.toBean(list, MesWmMiscIssueRespVO.class); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java new file mode 100644 index 000000000..ab7cb0d58 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/MesWmMiscIssueLineController.java @@ -0,0 +1,139 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO; +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.wm.miscissue.MesWmMiscIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +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.wm.miscissue.MesWmMiscIssueLineService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 杂项出库单行") +@RestController +@RequestMapping("/mes/wm/misc-issue-line") +@Validated +public class MesWmMiscIssueLineController { + + @Resource + private MesWmMiscIssueLineService miscIssueLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService warehouseLocationService; + + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + + @PostMapping("/create") + @Operation(summary = "创建杂项出库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:create')") + public CommonResult createMiscIssueLine(@Valid @RequestBody MesWmMiscIssueLineSaveReqVO createReqVO) { + return success(miscIssueLineService.createMiscIssueLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改杂项出库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:update')") + public CommonResult updateMiscIssueLine(@Valid @RequestBody MesWmMiscIssueLineSaveReqVO updateReqVO) { + miscIssueLineService.updateMiscIssueLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除杂项出库单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:delete')") + public CommonResult deleteMiscIssueLine(@RequestParam("id") Long id) { + miscIssueLineService.deleteMiscIssueLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得杂项出库单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:query')") + public CommonResult getMiscIssueLine(@RequestParam("id") Long id) { + MesWmMiscIssueLineDO line = miscIssueLineService.getMiscIssueLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得杂项出库单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-misc-issue:query')") + public CommonResult> getMiscIssueLinePage( + @Valid MesWmMiscIssueLinePageReqVO pageReqVO) { + PageResult pageResult = miscIssueLineService.getMiscIssueLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmMiscIssueLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmMiscIssueLineDO::getWarehouseId)); + Map locationMap = warehouseLocationService.getWarehouseLocationMap( + convertSet(list, MesWmMiscIssueLineDO::getLocationId)); + Map areaMap = warehouseAreaService.getWarehouseAreaMap( + convertSet(list, MesWmMiscIssueLineDO::getAreaId)); + + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmMiscIssueLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssuePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssuePageReqVO.java new file mode 100644 index 000000000..eb56ae1e4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssuePageReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 杂项出库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmMiscIssuePageReqVO extends PageParam { + + @Schema(description = "出库单编号", example = "MI20260302001") + private String code; + + @Schema(description = "出库单名称", example = "库存调整出库") + private String name; + + @Schema(description = "杂项类型", example = "1") + private Integer type; + + @Schema(description = "来源单据编号", example = "DOC20260302001") + private String sourceDocCode; + + @Schema(description = "来源单据类型", example = "PURCHASE_ORDER") + private String sourceDocType; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "出库日期范围") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] issueDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java new file mode 100644 index 000000000..cbab9242d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 杂项出库单 Response VO") +@Data +public class MesWmMiscIssueRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MI20260302001") + private String code; + + @Schema(description = "出库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "库存调整出库") + private String name; + + @Schema(description = "杂项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer type; + + @Schema(description = "来源单据ID", example = "1") + private Long sourceDocId; + + @Schema(description = "来源单据编号", example = "DOC20260302001") + private String sourceDocCode; + + @Schema(description = "来源单据类型", example = "PURCHASE_ORDER") + private String sourceDocType; + + @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime issueDate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueSaveReqVO.java new file mode 100644 index 000000000..2758b7ef2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 杂项出库单新增/修改 Request VO") +@Data +public class MesWmMiscIssueSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MI20260302001") + @NotBlank(message = "出库单编号不能为空") + private String code; + + @Schema(description = "出库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "库存调整出库") + @NotBlank(message = "出库单名称不能为空") + private String name; + + @Schema(description = "杂项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "杂项类型不能为空") + private Integer type; + + @Schema(description = "来源单据ID", example = "1") + private Long sourceDocId; + + @Schema(description = "来源单据编号", example = "DOC20260302001") + private String sourceDocCode; + + @Schema(description = "来源单据类型", example = "PURCHASE_ORDER") + private String sourceDocType; + + @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出库日期不能为空") + private LocalDateTime issueDate; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLinePageReqVO.java new file mode 100644 index 000000000..ba361e6ce --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 杂项出库单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmMiscIssueLinePageReqVO extends PageParam { + + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "出库单编号不能为空") + private Long issueId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java new file mode 100644 index 000000000..119733fed --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineRespVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 杂项出库单行 Response VO") +@Data +public class MesWmMiscIssueLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long issueId; + + @Schema(description = "来源单据行ID", example = "1") + private Long sourceDocLineId; + + @Schema(description = "库存记录ID", example = "1") + private Long materialStockId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "出库数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260301") + private String batchCode; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "仓库名称", example = "原料仓") + private String warehouseName; + + @Schema(description = "库区名称", example = "A区") + private String locationName; + + @Schema(description = "库位名称", example = "1排1架") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java new file mode 100644 index 000000000..d00500514 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/line/MesWmMiscIssueLineSaveReqVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 杂项出库单行新增/修改 Request VO") +@Data +public class MesWmMiscIssueLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "出库单编号不能为空") + private Long issueId; + + @Schema(description = "来源单据行ID", example = "1") + private Long sourceDocLineId; + + @Schema(description = "库存记录ID", example = "1") + private Long materialStockId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "出库数量不能为空") + @DecimalMin(value = "0.01", message = "出库数量必须大于0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260301") + private String batchCode; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库不能为空") + private Long warehouseId; + + @Schema(description = "库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库区不能为空") + private Long locationId; + + @Schema(description = "库位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库位不能为空") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptController.java new file mode 100644 index 000000000..55f7361b6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptController.java @@ -0,0 +1,123 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.miscreceipt.vo.MesWmMiscReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.MesWmMiscReceiptRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.MesWmMiscReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDO; +import cn.iocoder.yudao.module.mes.service.wm.miscreceipt.MesWmMiscReceiptService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * MES 杂项入库单 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 杂项入库单") +@RestController +@RequestMapping("/mes/wm/misc-receipt") +@Validated +public class MesWmMiscReceiptController { + + @Resource + private MesWmMiscReceiptService miscReceiptService; + + @PostMapping("/create") + @Operation(summary = "创建杂项入库单") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:create')") + public CommonResult createMiscReceipt(@Valid @RequestBody MesWmMiscReceiptSaveReqVO createReqVO) { + return success(miscReceiptService.createMiscReceipt(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改杂项入库单") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:update')") + public CommonResult updateMiscReceipt(@Valid @RequestBody MesWmMiscReceiptSaveReqVO updateReqVO) { + miscReceiptService.updateMiscReceipt(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除杂项入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:delete')") + public CommonResult deleteMiscReceipt(@RequestParam("id") Long id) { + miscReceiptService.deleteMiscReceipt(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得杂项入库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:query')") + public CommonResult getMiscReceipt(@RequestParam("id") Long id) { + MesWmMiscReceiptDO receipt = miscReceiptService.getMiscReceipt(id); + return success(BeanUtils.toBean(receipt, MesWmMiscReceiptRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得杂项入库单分页") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:query')") + public CommonResult> getMiscReceiptPage(@Valid MesWmMiscReceiptPageReqVO pageReqVO) { + PageResult pageResult = miscReceiptService.getMiscReceiptPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesWmMiscReceiptRespVO.class)); + } + + @PutMapping("/submit") + @Operation(summary = "提交审批") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:submit')") + public CommonResult submitMiscReceipt(@RequestParam("id") Long id) { + miscReceiptService.submitMiscReceipt(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "执行入库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:finish')") + public CommonResult finishMiscReceipt(@RequestParam("id") Long id) { + miscReceiptService.finishMiscReceipt(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消杂项入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:cancel')") + public CommonResult cancelMiscReceipt(@RequestParam("id") Long id) { + miscReceiptService.cancelMiscReceipt(id); + return success(true); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出杂项入库单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportMiscReceiptExcel(@Valid MesWmMiscReceiptPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(Integer.MAX_VALUE); + List list = miscReceiptService.getMiscReceiptPage(pageReqVO).getList(); + ExcelUtils.write(response, "杂项入库单.xls", "数据", MesWmMiscReceiptRespVO.class, + BeanUtils.toBean(list, MesWmMiscReceiptRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptLineController.java new file mode 100644 index 000000000..8d6d93d67 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/MesWmMiscReceiptLineController.java @@ -0,0 +1,150 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; +import cn.iocoder.yudao.module.mes.service.wm.miscreceipt.MesWmMiscReceiptLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +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.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +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.wm.warehouse.MesWmWarehouseService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; + +/** + * MES 杂项入库单行 Controller + */ +@Tag(name = "管理后台 - MES 杂项入库单行") +@RestController +@RequestMapping("/mes/wm/misc-receipt-line") +@Validated +public class MesWmMiscReceiptLineController { + + @Resource + private MesWmMiscReceiptLineService miscReceiptLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService warehouseLocationService; + + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + + @PostMapping("/create") + @Operation(summary = "创建杂项入库单行") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:create')") + public CommonResult createMiscReceiptLine(@Valid @RequestBody MesWmMiscReceiptLineSaveReqVO createReqVO) { + return success(miscReceiptLineService.createMiscReceiptLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改杂项入库单行") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:update')") + public CommonResult updateMiscReceiptLine(@Valid @RequestBody MesWmMiscReceiptLineSaveReqVO updateReqVO) { + miscReceiptLineService.updateMiscReceiptLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除杂项入库单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:delete')") + public CommonResult deleteMiscReceiptLine(@RequestParam("id") Long id) { + miscReceiptLineService.deleteMiscReceiptLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得杂项入库单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:query')") + public CommonResult getMiscReceiptLine(@RequestParam("id") Long id) { + MesWmMiscReceiptLineDO line = miscReceiptLineService.getMiscReceiptLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/list-by-receipt-id") + @Operation(summary = "获得杂项入库单行列表") + @Parameter(name = "receiptId", description = "入库单编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:query')") + public CommonResult> getMiscReceiptLineListByReceiptId(@RequestParam("receiptId") Long receiptId) { + List list = miscReceiptLineService.getMiscReceiptLineListByReceiptId(receiptId); + return success(buildRespVOList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得杂项入库单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm:misc-receipt:query')") + public CommonResult> getMiscReceiptLinePage(@Valid MesWmMiscReceiptLinePageReqVO pageReqVO) { + PageResult pageResult = miscReceiptLineService.getMiscReceiptLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmMiscReceiptLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmMiscReceiptLineDO::getWarehouseId)); + Map locationMap = warehouseLocationService.getWarehouseLocationMap( + convertSet(list, MesWmMiscReceiptLineDO::getLocationId)); + Map areaMap = warehouseAreaService.getWarehouseAreaMap( + convertSet(list, MesWmMiscReceiptLineDO::getAreaId)); + + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmMiscReceiptLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptPageReqVO.java new file mode 100644 index 000000000..13589e8a7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptPageReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 杂项入库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmMiscReceiptPageReqVO extends PageParam { + + @Schema(description = "入库单编码", example = "MR2026030001") + private String code; + + @Schema(description = "入库单名称", example = "退料入库单") + private String name; + + @Schema(description = "杂项类型", example = "1") + private Integer type; + + @Schema(description = "来源单据编号", example = "DOC2026030001") + private String sourceDocCode; + + @Schema(description = "来源单据类型", example = "WORK_ORDER") + private String sourceDocType; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "入库日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] receiptDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java new file mode 100644 index 000000000..e29fc879d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 杂项入库单 Response VO") +@Data +public class MesWmMiscReceiptRespVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单编码", example = "MR2026030001") + private String code; + + @Schema(description = "入库单名称", example = "退料入库单") + private String name; + + @Schema(description = "杂项类型", example = "1") + private Integer type; + + @Schema(description = "来源单据 ID", example = "1") + private Long sourceDocId; + + @Schema(description = "来源单据编码", example = "WO2026030001") + private String sourceDocCode; + + @Schema(description = "来源单据类型", example = "WORK_ORDER") + private String sourceDocType; + + @Schema(description = "入库日期") + private LocalDateTime receiptDate; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptSaveReqVO.java new file mode 100644 index 000000000..1815c0513 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 杂项入库单新增/修改 Request VO") +@Data +public class MesWmMiscReceiptSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "MR2026030001") + @NotEmpty(message = "入库单编码不能为空") + private String code; + + @Schema(description = "入库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "退料入库单") + @NotEmpty(message = "入库单名称不能为空") + private String name; + + @Schema(description = "杂项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "杂项类型不能为空") + private Integer type; + + @Schema(description = "来源单据 ID", example = "1") + private Long sourceDocId; + + @Schema(description = "来源单据编码", example = "WO2026030001") + private String sourceDocCode; + + @Schema(description = "来源单据类型", example = "WORK_ORDER") + private String sourceDocType; + + @Schema(description = "入库日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "入库日期不能为空") + private LocalDateTime receiptDate; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLinePageReqVO.java new file mode 100644 index 000000000..908656789 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 杂项入库单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmMiscReceiptLinePageReqVO extends PageParam { + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单编号不能为空") + private Long receiptId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineRespVO.java new file mode 100644 index 000000000..6e7ba6215 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineRespVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 杂项入库单行 Response VO") +@Data +public class MesWmMiscReceiptLineRespVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单编号", example = "1") + private Long receiptId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "入库数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次号", example = "BATCH20260301") + private String batchCode; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "仓库名称", example = "原料仓") + private String warehouseName; + + @Schema(description = "库区名称", example = "A区") + private String locationName; + + @Schema(description = "库位名称", example = "1排1架") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineSaveReqVO.java new file mode 100644 index 000000000..5eaf18711 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/line/MesWmMiscReceiptLineSaveReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 杂项入库单行新增/修改 Request VO") +@Data +public class MesWmMiscReceiptLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单编号不能为空") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料不能为空") + private Long itemId; + + @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "入库数量不能为空") + @DecimalMin(value = "0.01", message = "入库数量不能小于 0.01") + private BigDecimal quantity; + + @Schema(description = "批次号", example = "BATCH20260301") + private String batchCode; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库不能为空") + private Long warehouseId; + + @Schema(description = "库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库区不能为空") + private Long locationId; + + @Schema(description = "库位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库位不能为空") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueController.java new file mode 100644 index 000000000..54548ff29 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueController.java @@ -0,0 +1,179 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.outsourceissue.MesWmOutsourceIssueService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +/** + * MES 外协发料单 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 外协发料单") +@RestController +@RequestMapping("/mes/wm/outsource-issue") +@Validated +public class MesWmOutsourceIssueController { + + @Resource + private MesWmOutsourceIssueService outsourceIssueService; + + @Resource + private MesMdVendorService vendorService; + @Resource + private MesProWorkOrderService workOrderService; + + @PostMapping("/create") + @Operation(summary = "创建外协发料单") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:create')") + public CommonResult createOutsourceIssue(@Valid @RequestBody MesWmOutsourceIssueSaveReqVO createReqVO) { + return success(outsourceIssueService.createOutsourceIssue(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改外协发料单") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:update')") + public CommonResult updateOutsourceIssue(@Valid @RequestBody MesWmOutsourceIssueSaveReqVO updateReqVO) { + outsourceIssueService.updateOutsourceIssue(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除外协发料单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:delete')") + public CommonResult deleteOutsourceIssue(@RequestParam("id") Long id) { + outsourceIssueService.deleteOutsourceIssue(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得外协发料单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:query')") + public CommonResult getOutsourceIssue(@RequestParam("id") Long id) { + MesWmOutsourceIssueDO issue = outsourceIssueService.getOutsourceIssue(id); + if (issue == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(issue)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得外协发料单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:query')") + public CommonResult> getOutsourceIssuePage( + @Valid MesWmOutsourceIssuePageReqVO pageReqVO) { + PageResult pageResult = outsourceIssueService.getOutsourceIssuePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出外协发料单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportOutsourceIssueExcel(@Valid MesWmOutsourceIssuePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = outsourceIssueService.getOutsourceIssuePage(pageReqVO); + ExcelUtils.write(response, "外协发料单.xls", "数据", MesWmOutsourceIssueRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交到待拣货") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:update')") + public CommonResult submitOutsourceIssue(@RequestParam("id") Long id) { + outsourceIssueService.submitOutsourceIssue(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "执行拣货") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:update')") + public CommonResult stockOutsourceIssue(@RequestParam("id") Long id) { + outsourceIssueService.stockOutsourceIssue(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成外协发料出库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:finish')") + public CommonResult finishOutsourceIssue(@RequestParam("id") Long id) { + outsourceIssueService.finishOutsourceIssue(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消外协发料单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:update')") + public CommonResult cancelOutsourceIssue(@RequestParam("id") Long id) { + outsourceIssueService.cancelOutsourceIssue(id); + return success(true); + } + + @GetMapping("/check-quantity") + @Operation(summary = "校验外协发料单数量", description = "校验每行明细数量之和是否等于行发料数量") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:query')") + public CommonResult checkOutsourceIssueQuantity(@RequestParam("id") Long id) { + return success(outsourceIssueService.checkOutsourceIssueQuantity(id)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesWmOutsourceIssueDO::getVendorId)); + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesWmOutsourceIssueDO::getWorkOrderId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmOutsourceIssueRespVO.class, vo -> { + MapUtils.findAndThen(vendorMap, vo.getVendorId(), vendor -> + vo.setVendorCode(vendor.getCode()).setVendorName(vendor.getName())); + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder -> + vo.setWorkOrderCode(workOrder.getCode()).setWorkOrderName(workOrder.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueDetailController.java new file mode 100644 index 000000000..526e43b8b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueDetailController.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO; +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.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.outsourceissue.MesWmOutsourceIssueDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * MES 外协发料单明细 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 外协发料单明细") +@RestController +@RequestMapping("/mes/wm/outsource-issue-detail") +@Validated +public class MesWmOutsourceIssueDetailController { + + @Resource + private MesWmOutsourceIssueDetailService outsourceIssueDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建外协发料单明细") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:create')") + public CommonResult createOutsourceIssueDetail(@Valid @RequestBody MesWmOutsourceIssueDetailSaveReqVO createReqVO) { + return success(outsourceIssueDetailService.createOutsourceIssueDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改外协发料单明细") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:update')") + public CommonResult updateOutsourceIssueDetail(@Valid @RequestBody MesWmOutsourceIssueDetailSaveReqVO updateReqVO) { + outsourceIssueDetailService.updateOutsourceIssueDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除外协发料单明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:delete')") + public CommonResult deleteOutsourceIssueDetail(@RequestParam("id") Long id) { + outsourceIssueDetailService.deleteOutsourceIssueDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得外协发料单明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:query')") + public CommonResult getOutsourceIssueDetail(@RequestParam("id") Long id) { + MesWmOutsourceIssueDetailDO detail = outsourceIssueDetailService.getOutsourceIssueDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得外协发料单明细列表(按行ID)") + @Parameter(name = "lineId", description = "行ID", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:query')") + public CommonResult> getOutsourceIssueDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = outsourceIssueDetailService.getOutsourceIssueDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmOutsourceIssueDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmOutsourceIssueDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmOutsourceIssueDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmOutsourceIssueDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmOutsourceIssueDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueLineController.java new file mode 100644 index 000000000..11ac9d5ba --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/MesWmOutsourceIssueLineController.java @@ -0,0 +1,142 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineSaveReqVO; +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.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +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.wm.batch.MesWmBatchService; +import cn.iocoder.yudao.module.mes.service.wm.outsourceissue.MesWmOutsourceIssueLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * MES 外协发料单行 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 外协发料单行") +@RestController +@RequestMapping("/mes/wm/outsource-issue-line") +@Validated +public class MesWmOutsourceIssueLineController { + + @Resource + private MesWmOutsourceIssueLineService outsourceIssueLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmBatchService batchService; + + @PostMapping("/create") + @Operation(summary = "创建外协发料单行") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:create')") + public CommonResult createOutsourceIssueLine(@Valid @RequestBody MesWmOutsourceIssueLineSaveReqVO createReqVO) { + return success(outsourceIssueLineService.createOutsourceIssueLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改外协发料单行") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:update')") + public CommonResult updateOutsourceIssueLine(@Valid @RequestBody MesWmOutsourceIssueLineSaveReqVO updateReqVO) { + outsourceIssueLineService.updateOutsourceIssueLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除外协发料单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:delete')") + public CommonResult deleteOutsourceIssueLine(@RequestParam("id") Long id) { + outsourceIssueLineService.deleteOutsourceIssueLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得外协发料单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:query')") + public CommonResult getOutsourceIssueLine(@RequestParam("id") Long id) { + MesWmOutsourceIssueLineDO line = outsourceIssueLineService.getOutsourceIssueLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得外协发料单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:query')") + public CommonResult> getOutsourceIssueLinePage( + @Valid MesWmOutsourceIssueLinePageReqVO pageReqVO) { + PageResult pageResult = outsourceIssueLineService.getOutsourceIssueLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/list-by-issue-id") + @Operation(summary = "获得外协发料单行列表") + @Parameter(name = "issueId", description = "发料单ID", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-issue:query')") + public CommonResult> getOutsourceIssueLineListByIssueId( + @RequestParam("issueId") Long issueId) { + List list = outsourceIssueLineService.getOutsourceIssueLineListByIssueId(issueId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmOutsourceIssueLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 1.2 获得批次数据 + Set batchIds = convertSet(list, MesWmOutsourceIssueLineDO::getBatchId); + batchIds.remove(null); + Map batchMap = CollUtil.isEmpty(batchIds) ? Collections.emptyMap() + : convertMap(batchIds, id -> id, id -> batchService.getBatch(id)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmOutsourceIssueLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(batchMap, vo.getBatchId(), batch -> vo.setBatchCode(batch.getCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssuePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssuePageReqVO.java new file mode 100644 index 000000000..5419da3ae --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssuePageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 外协发料单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmOutsourceIssuePageReqVO extends PageParam { + + @Schema(description = "发料单编号", example = "WOS202603020001") + private String code; + + @Schema(description = "发料单名称", example = "外协发料单001") + private String name; + + @Schema(description = "供应商ID", example = "1") + private Long vendorId; + + @Schema(description = "生产工单ID", example = "1") + private Long workOrderId; + + @Schema(description = "发料日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] issueDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueRespVO.java new file mode 100644 index 000000000..ad6a39e01 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueRespVO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协发料单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmOutsourceIssueRespVO { + + @Schema(description = "发料单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("发料单ID") + private Long id; + + @Schema(description = "发料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "WOS202603020001") + @ExcelProperty("发料单编号") + private String code; + + @Schema(description = "发料单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "外协发料单001") + @ExcelProperty("发料单名称") + private String name; + + @Schema(description = "供应商ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long vendorId; + + @Schema(description = "供应商编码", example = "V001") + @ExcelProperty("供应商编码") + private String vendorCode; + + @Schema(description = "供应商名称", example = "供应商A") + @ExcelProperty("供应商名称") + private String vendorName; + + @Schema(description = "生产工单ID", example = "1") + private Long workOrderId; + + @Schema(description = "生产工单编码", example = "WO202603020001") + @ExcelProperty("生产工单编码") + private String workOrderCode; + + @Schema(description = "生产工单名称", example = "生产工单001") + @ExcelProperty("生产工单名称") + private String workOrderName; + + @Schema(description = "发料日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("发料日期") + private LocalDateTime issueDate; + + @Schema(description = "单据状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("单据状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueSaveReqVO.java new file mode 100644 index 000000000..3b5a02e59 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueSaveReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协发料单新增/修改 Request VO") +@Data +public class MesWmOutsourceIssueSaveReqVO { + + @Schema(description = "发料单ID", example = "1024") + private Long id; + + @Schema(description = "发料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "WOS202603020001") + @NotEmpty(message = "发料单编号不能为空") + private String code; + + @Schema(description = "发料单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "外协发料单001") + @NotEmpty(message = "发料单名称不能为空") + private String name; + + @Schema(description = "供应商ID", example = "1") + private Long vendorId; + + @Schema(description = "生产工单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "生产工单ID不能为空") + private Long workOrderId; + + @Schema(description = "发料日期") + private LocalDateTime issueDate; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/detail/MesWmOutsourceIssueDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/detail/MesWmOutsourceIssueDetailRespVO.java new file mode 100644 index 000000000..66f18b29d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/detail/MesWmOutsourceIssueDetailRespVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协发料单明细 Response VO") +@Data +public class MesWmOutsourceIssueDetailRespVO { + + @Schema(description = "明细ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "行ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long lineId; + + @Schema(description = "发料单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long issueId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "数量", example = "300.00") + private BigDecimal quantity; + + @Schema(description = "库存ID", example = "1") + private Long materialStockId; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "BATCH001") + private String batchCode; + + @Schema(description = "仓库ID", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原料仓") + private String warehouseName; + + @Schema(description = "库区ID", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A 区") + private String locationName; + + @Schema(description = "库位ID", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A-01") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/detail/MesWmOutsourceIssueDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/detail/MesWmOutsourceIssueDetailSaveReqVO.java new file mode 100644 index 000000000..b29ba6731 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/detail/MesWmOutsourceIssueDetailSaveReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 外协发料单明细新增/修改 Request VO") +@Data +public class MesWmOutsourceIssueDetailSaveReqVO { + + @Schema(description = "明细ID", example = "1024") + private Long id; + + @Schema(description = "行ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "行ID不能为空") + private Long lineId; + + @Schema(description = "发料单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "发料单ID不能为空") + private Long issueId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料ID不能为空") + private Long itemId; + + @Schema(description = "库存ID", example = "1") + private Long materialStockId; + + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") + @NotNull(message = "数量不能为空") + @DecimalMin(value = "0.01", message = "数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "仓库ID", example = "1") + private Long warehouseId; + + @Schema(description = "库区ID", example = "1") + private Long locationId; + + @Schema(description = "库位ID", example = "1") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLinePageReqVO.java new file mode 100644 index 000000000..a121446fe --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 外协发料单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmOutsourceIssueLinePageReqVO extends PageParam { + + @Schema(description = "发料单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "发料单ID不能为空") + private Long issueId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineRespVO.java new file mode 100644 index 000000000..753e971d8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineRespVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协发料单行 Response VO") +@Data +public class MesWmOutsourceIssueLineRespVO { + + @Schema(description = "行ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "发料单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long issueId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "发料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00") + private BigDecimal quantity; + + @Schema(description = "库存ID", example = "1") + private Long materialStockId; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "BATCH001") + private String batchCode; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineSaveReqVO.java new file mode 100644 index 000000000..7bfabd0a3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/line/MesWmOutsourceIssueLineSaveReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 外协发料单行新增/修改 Request VO") +@Data +public class MesWmOutsourceIssueLineSaveReqVO { + + @Schema(description = "行ID", example = "1024") + private Long id; + + @Schema(description = "发料单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "发料单ID不能为空") + private Long issueId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料ID不能为空") + private Long itemId; + + @Schema(description = "发料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00") + @NotNull(message = "发料数量不能为空") + @DecimalMin(value = "0.01", message = "发料数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "库存ID", example = "1") + private Long materialStockId; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "批次编码", example = "BATCH001") + private String batchCode; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptController.java new file mode 100644 index 000000000..a2dadef98 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptController.java @@ -0,0 +1,167 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.outsourcereceipt.vo.MesWmOutsourceReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 外协入库单") +@RestController +@RequestMapping("/mes/wm/outsource-receipt") +@Validated +public class MesWmOutsourceReceiptController { + + @Resource + private MesWmOutsourceReceiptService outsourceReceiptService; + + @Resource + private MesMdVendorService vendorService; + + @Resource + private MesProWorkOrderService workOrderService; + + @PostMapping("/create") + @Operation(summary = "创建外协入库单") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:create')") + public CommonResult createOutsourceReceipt(@Valid @RequestBody MesWmOutsourceReceiptSaveReqVO createReqVO) { + return success(outsourceReceiptService.createOutsourceReceipt(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改外协入库单") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:update')") + public CommonResult updateOutsourceReceipt(@Valid @RequestBody MesWmOutsourceReceiptSaveReqVO updateReqVO) { + outsourceReceiptService.updateOutsourceReceipt(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除外协入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:delete')") + public CommonResult deleteOutsourceReceipt(@RequestParam("id") Long id) { + outsourceReceiptService.deleteOutsourceReceipt(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得外协入库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:query')") + public CommonResult getOutsourceReceipt(@RequestParam("id") Long id) { + MesWmOutsourceReceiptDO receipt = outsourceReceiptService.getOutsourceReceipt(id); + if (receipt == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(receipt)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得外协入库单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:query')") + public CommonResult> getOutsourceReceiptPage( + @Valid MesWmOutsourceReceiptPageReqVO pageReqVO) { + PageResult pageResult = outsourceReceiptService.getOutsourceReceiptPage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出外协入库单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportOutsourceReceiptExcel(@Valid MesWmOutsourceReceiptPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = outsourceReceiptService.getOutsourceReceiptPage(pageReqVO); + ExcelUtils.write(response, "外协入库单.xls", "数据", MesWmOutsourceReceiptRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交外协入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:update')") + public CommonResult submitOutsourceReceipt(@RequestParam("id") Long id) { + outsourceReceiptService.submitOutsourceReceipt(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "执行上架") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:update')") + public CommonResult stockOutsourceReceipt(@RequestParam("id") Long id) { + outsourceReceiptService.stockOutsourceReceipt(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成入库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:finish')") + public CommonResult finishOutsourceReceipt(@RequestParam("id") Long id) { + outsourceReceiptService.finishOutsourceReceipt(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消外协入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:update')") + public CommonResult cancelOutsourceReceipt(@RequestParam("id") Long id) { + outsourceReceiptService.cancelOutsourceReceipt(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesWmOutsourceReceiptDO::getVendorId)); + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesWmOutsourceReceiptDO::getWorkOrderId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmOutsourceReceiptRespVO.class, vo -> { + MapUtils.findAndThen(vendorMap, vo.getVendorId(), + vendor -> vo.setVendorName(vendor.getName())); + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), + workOrder -> vo.setWorkOrderCode(workOrder.getCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptDetailController.java new file mode 100644 index 000000000..090735814 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptDetailController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.detail.MesWmOutsourceReceiptDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.detail.MesWmOutsourceReceiptDetailSaveReqVO; +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.wm.outsourcereceipt.MesWmOutsourceReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.outsourcereceipt.MesWmOutsourceReceiptDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 外协入库明细") +@RestController +@RequestMapping("/mes/wm/outsource-receipt-detail") +@Validated +public class MesWmOutsourceReceiptDetailController { + + @Resource + private MesWmOutsourceReceiptDetailService detailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建外协入库明细") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:create')") + public CommonResult createOutsourceReceiptDetail(@Valid @RequestBody MesWmOutsourceReceiptDetailSaveReqVO createReqVO) { + return success(detailService.createOutsourceReceiptDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改外协入库明细") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:update')") + public CommonResult updateOutsourceReceiptDetail(@Valid @RequestBody MesWmOutsourceReceiptDetailSaveReqVO updateReqVO) { + detailService.updateOutsourceReceiptDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除外协入库明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:delete')") + public CommonResult deleteOutsourceReceiptDetail(@RequestParam("id") Long id) { + detailService.deleteOutsourceReceiptDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得外协入库明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:query')") + public CommonResult getOutsourceReceiptDetail(@RequestParam("id") Long id) { + MesWmOutsourceReceiptDetailDO detail = detailService.getOutsourceReceiptDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得外协入库明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:query')") + public CommonResult> getOutsourceReceiptDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = detailService.getOutsourceReceiptDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmOutsourceReceiptDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmOutsourceReceiptDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmOutsourceReceiptDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmOutsourceReceiptDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmOutsourceReceiptDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptLineController.java new file mode 100644 index 000000000..91f8280c1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/MesWmOutsourceReceiptLineController.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line.MesWmOutsourceReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line.MesWmOutsourceReceiptLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line.MesWmOutsourceReceiptLineSaveReqVO; +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.wm.outsourcereceipt.MesWmOutsourceReceiptLineDO; +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.wm.outsourcereceipt.MesWmOutsourceReceiptLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 外协入库单行") +@RestController +@RequestMapping("/mes/wm/outsource-receipt-line") +@Validated +public class MesWmOutsourceReceiptLineController { + + @Resource + private MesWmOutsourceReceiptLineService receiptLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建外协入库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:create')") + public CommonResult createOutsourceReceiptLine(@Valid @RequestBody MesWmOutsourceReceiptLineSaveReqVO createReqVO) { + return success(receiptLineService.createOutsourceReceiptLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改外协入库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:update')") + public CommonResult updateOutsourceReceiptLine(@Valid @RequestBody MesWmOutsourceReceiptLineSaveReqVO updateReqVO) { + receiptLineService.updateOutsourceReceiptLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除外协入库单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:delete')") + public CommonResult deleteOutsourceReceiptLine(@RequestParam("id") Long id) { + receiptLineService.deleteOutsourceReceiptLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得外协入库单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:query')") + public CommonResult getOutsourceReceiptLine(@RequestParam("id") Long id) { + MesWmOutsourceReceiptLineDO line = receiptLineService.getOutsourceReceiptLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得外协入库单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-outsource-receipt:query')") + public CommonResult> getOutsourceReceiptLinePage( + @Valid MesWmOutsourceReceiptLinePageReqVO pageReqVO) { + PageResult pageResult = receiptLineService.getOutsourceReceiptLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmOutsourceReceiptLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmOutsourceReceiptLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptPageReqVO.java new file mode 100644 index 000000000..714e03572 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptPageReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 外协入库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmOutsourceReceiptPageReqVO extends PageParam { + + @Schema(description = "入库单编码", example = "OR2026030001") + private String code; + + @Schema(description = "入库单名称", example = "外协加工入库单") + private String name; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "入库日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] receiptDate; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "外协工单编码", example = "WO2026030001") + private String workOrderCode; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptRespVO.java new file mode 100644 index 000000000..749fc53f1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptRespVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协入库单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmOutsourceReceiptRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "入库单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "OR2026030001") + @ExcelProperty("入库单编码") + private String code; + + @Schema(description = "入库单名称", example = "外协加工入库单") + @ExcelProperty("入库单名称") + private String name; + + @Schema(description = "外协工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "外协工单编码", example = "WO20260301") + @ExcelProperty("外协工单") + private String workOrderCode; + + @Schema(description = "供应商编号", example = "1") + private Long vendorId; + + @Schema(description = "供应商名称", example = "某供应商") + @ExcelProperty("供应商") + private String vendorName; + + @Schema(description = "入库日期") + @ExcelProperty("入库日期") + private LocalDateTime receiptDate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptSaveReqVO.java new file mode 100644 index 000000000..3bc3566ef --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptSaveReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协入库单新增/修改 Request VO") +@Data +public class MesWmOutsourceReceiptSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "OR2026030001") + @NotEmpty(message = "入库单编码不能为空") + private String code; + + @Schema(description = "入库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "外协加工入库单") + @NotEmpty(message = "入库单名称不能为空") + private String name; + + @Schema(description = "外协工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "外协工单不能为空") + private Long workOrderId; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "供应商不能为空") + private Long vendorId; + + @Schema(description = "入库日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "入库日期不能为空") + private LocalDateTime receiptDate; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/detail/MesWmOutsourceReceiptDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/detail/MesWmOutsourceReceiptDetailRespVO.java new file mode 100644 index 000000000..b2dac6794 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/detail/MesWmOutsourceReceiptDetailRespVO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协入库明细 Response VO") +@Data +public class MesWmOutsourceReceiptDetailRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "入库单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long lineId; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "加工件") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "件") + private String unitMeasureName; + + @Schema(description = "上架数量", example = "300.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "成品仓") + private String warehouseName; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A 区") + private String locationName; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A-01") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/detail/MesWmOutsourceReceiptDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/detail/MesWmOutsourceReceiptDetailSaveReqVO.java new file mode 100644 index 000000000..2d8124a83 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/detail/MesWmOutsourceReceiptDetailSaveReqVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 外协入库明细新增/修改 Request VO") +@Data +public class MesWmOutsourceReceiptDetailSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单行编号不能为空") + private Long lineId; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单编号不能为空") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "上架数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") + @NotNull(message = "上架数量不能为空") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLinePageReqVO.java new file mode 100644 index 000000000..e99802c19 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLinePageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 外协入库单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmOutsourceReceiptLinePageReqVO extends PageParam { + + @Schema(description = "入库单编号", example = "1") + private Long receiptId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLineRespVO.java new file mode 100644 index 000000000..c092817eb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLineRespVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协入库单行 Response VO") +@Data +public class MesWmOutsourceReceiptLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "加工件") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "件") + private String unitMeasureName; + + @Schema(description = "入库数量", example = "500.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "BATCH20260301001") + private String batchCode; + + @Schema(description = "生产日期") + private LocalDateTime productionDate; + + @Schema(description = "有效期") + private LocalDateTime expireDate; + + @Schema(description = "生产批号", example = "PB20260301") + private String lotNumber; + + @Schema(description = "是否需要质检") + private Boolean iqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLineSaveReqVO.java new file mode 100644 index 000000000..33bd341d0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/line/MesWmOutsourceReceiptLineSaveReqVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 外协入库单行新增/修改 Request VO") +@Data +public class MesWmOutsourceReceiptLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "入库单编号不能为空") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00") + @NotNull(message = "入库数量不能为空") + private BigDecimal quantity; + + @Schema(description = "生产日期") + private LocalDateTime productionDate; + + @Schema(description = "有效期") + private LocalDateTime expireDate; + + @Schema(description = "生产批号", example = "PB20260301") + private String lotNumber; + + @Schema(description = "是否需要质检") + private Boolean iqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/package-info.java new file mode 100644 index 000000000..74b90ae29 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/package-info.java @@ -0,0 +1,4 @@ +/** + * MES 仓库管理(Warehouse Management):仓库/库区/库位、库存台账、批次/SN、出入库(采购/生产/销售/外协/其他)、调拨、盘点、条码 + */ +package cn.iocoder.yudao.module.mes.controller.admin.wm; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java new file mode 100644 index 000000000..70b4d0f1b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java @@ -0,0 +1,172 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.packages; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.wm.packages.MesWmPackageService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import java.util.stream.Stream; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; + +// DONE @AI:检查下 java 类,是不是 author 没加。 +/** + * MES 装箱单 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 装箱单") +@RestController +@RequestMapping("/mes/wm/package") +@Validated +public class MesWmPackageController { + + @Resource + private MesWmPackageService packageService; + @Resource + private MesMdClientService clientService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建装箱单") + @PreAuthorize("@ss.hasPermission('mes:wm-package:create')") + public CommonResult createPackage(@Valid @RequestBody MesWmPackageSaveReqVO createReqVO) { + return success(packageService.createPackage(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改装箱单") + @PreAuthorize("@ss.hasPermission('mes:wm-package:update')") + public CommonResult updatePackage(@Valid @RequestBody MesWmPackageSaveReqVO updateReqVO) { + packageService.updatePackage(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除装箱单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-package:delete')") + public CommonResult deletePackage(@RequestParam("id") Long id) { + packageService.deletePackage(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得装箱单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')") + public CommonResult getPackage(@RequestParam("id") Long id) { + MesWmPackageDO packageDO = packageService.getPackage(id); + if (packageDO == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(packageDO)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得装箱单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')") + public CommonResult> getPackagePage( + @Valid MesWmPackagePageReqVO pageReqVO) { + PageResult pageResult = packageService.getPackagePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @PutMapping("/finish") + @Operation(summary = "完成装箱单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-package:update')") + public CommonResult finishPackage(@RequestParam("id") Long id) { + packageService.finishPackage(id); + return success(true); + } + + @PutMapping("/add-child-package") + @Operation(summary = "添加子箱") + @PreAuthorize("@ss.hasPermission('mes:wm-package:update')") + public CommonResult addChildPackage(@RequestParam("parentId") Long parentId, + @RequestParam("childId") Long childId) { + packageService.addChildPackage(parentId, childId); + return success(true); + } + + @PutMapping("/remove-child-package") + @Operation(summary = "移除子箱") + @Parameter(name = "childId", description = "子箱编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-package:update')") + public CommonResult removeChildPackage(@RequestParam("childId") Long childId) { + packageService.removeChildPackage(childId); + return success(true); + } + + @GetMapping("/childable-simple-list") + @Operation(summary = "可添加为子箱的装箱单精简列表") + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')") + public CommonResult> getChildablePackageSimpleList() { + List list = packageService.getChildablePackageList(); + return success(buildRespVOList(list)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得装箱单精简列表", description = "主要用于前端的下拉选项") + public CommonResult> getPackageSimpleList() { + List list = packageService.getPackageSimpleList(); + return success(buildRespVOList(list)); + } + + // ========== 私有方法 ========== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询客户 + Map clientMap = clientService.getClientMap( + convertSet(list, MesWmPackageDO::getClientId)); + // 批量查询计量单位(尺寸 + 重量) + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSetByFlatMap(list, p -> Stream.of(p.getSizeUnitId(), p.getWeightUnitId()))); + // 批量查询检查员 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesWmPackageDO::getInspectorUserId)); + // 构建返回结果 + return BeanUtils.toBean(list, MesWmPackageRespVO.class, vo -> { + MapUtils.findAndThen(clientMap, vo.getClientId(), + client -> vo.setClientCode(client.getCode()).setClientName(client.getName()) + .setClientNickname(client.getNickname())); + MapUtils.findAndThen(unitMeasureMap, vo.getSizeUnitId(), + unit -> vo.setSizeUnitName(unit.getName())); + MapUtils.findAndThen(unitMeasureMap, vo.getWeightUnitId(), + unit -> vo.setWeightUnitName(unit.getName())); + MapUtils.findAndThen(userMap, vo.getInspectorUserId(), + user -> vo.setInspectorName(user.getNickname())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageLineController.java new file mode 100644 index 000000000..12ae8c1ab --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageLineController.java @@ -0,0 +1,129 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.packages; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPackageLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPackageLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPackageLineSaveReqVO; +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.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO; +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.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.packages.MesWmPackageLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * MES 装箱明细 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 装箱明细") +@RestController +@RequestMapping("/mes/wm/package-line") +@Validated +public class MesWmPackageLineController { + + @Resource + private MesWmPackageLineService packageLineService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesProWorkOrderService workOrderService; + + @PostMapping("/create") + @Operation(summary = "创建装箱明细") + @PreAuthorize("@ss.hasPermission('mes:wm-package:create')") + public CommonResult createPackageLine(@Valid @RequestBody MesWmPackageLineSaveReqVO createReqVO) { + return success(packageLineService.createPackageLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改装箱明细") + @PreAuthorize("@ss.hasPermission('mes:wm-package:update')") + public CommonResult updatePackageLine(@Valid @RequestBody MesWmPackageLineSaveReqVO updateReqVO) { + packageLineService.updatePackageLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除装箱明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-package:delete')") + public CommonResult deletePackageLine(@RequestParam("id") Long id) { + packageLineService.deletePackageLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得装箱明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')") + public CommonResult getPackageLine(@RequestParam("id") Long id) { + MesWmPackageLineDO line = packageLineService.getPackageLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得装箱明细分页") + @PreAuthorize("@ss.hasPermission('mes:wm-package:query')") + public CommonResult> getPackageLinePage( + @Valid MesWmPackageLinePageReqVO pageReqVO) { + PageResult pageResult = packageLineService.getPackageLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ========== 私有方法 ========== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 批量查询物料 + Map itemMap = itemService + .getItemMap(convertSet(list, MesWmPackageLineDO::getItemId)); + // 批量查询计量单位 + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 批量查询工单 + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesWmPackageLineDO::getWorkOrderId)); + // 拼接数据 + return BeanUtils.toBean(list, MesWmPackageLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()) + .setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unit -> vo.setUnitMeasureName(unit.getName())); + }); + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), + workOrder -> vo.setWorkOrderCode(workOrder.getCode()) + .setBatchCode(workOrder.getBatchCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackagePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackagePageReqVO.java new file mode 100644 index 000000000..08cb21953 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackagePageReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * MES 装箱单分页 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 装箱单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmPackagePageReqVO extends PageParam { + + @Schema(description = "装箱单编号", example = "PKG") + private String code; + + @Schema(description = "销售订单编号", example = "SO") + private String salesOrderCode; + + @Schema(description = "客户 ID", example = "1") + private Long clientId; + + @Schema(description = "父箱 ID", example = "1024") + private Long parentId; + + @Schema(description = "检查员用户 ID", example = "1") + private Long inspectorUserId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageRespVO.java new file mode 100644 index 000000000..a5aed09f8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageRespVO.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 装箱单 Response VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 装箱单 Response VO") +@Data +@Accessors(chain = true) +@ExcelIgnoreUnannotated +public class MesWmPackageRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "装箱单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "PKG20260307001") + @ExcelProperty("装箱单编号") + private String code; + + @Schema(description = "父箱 ID", example = "0") + private Long parentId; + + @Schema(description = "装箱日期") + @ExcelProperty("装箱日期") + private LocalDateTime packageDate; + + @Schema(description = "销售订单编号", example = "SO20260301") + @ExcelProperty("销售订单编号") + private String salesOrderCode; + + @Schema(description = "发票编号", example = "INV20260301") + @ExcelProperty("发票编号") + private String invoiceCode; + + @Schema(description = "客户 ID", example = "1") + private Long clientId; + + @Schema(description = "客户编码", example = "C001") + @ExcelProperty("客户编码") + private String clientCode; + + @Schema(description = "客户名称", example = "某客户") + @ExcelProperty("客户名称") + private String clientName; + + @Schema(description = "客户简称", example = "某客户简称") + private String clientNickname; + + @Schema(description = "箱长度", example = "60.00") + @ExcelProperty("箱长度") + private BigDecimal length; + + @Schema(description = "箱宽度", example = "40.00") + @ExcelProperty("箱宽度") + private BigDecimal width; + + @Schema(description = "箱高度", example = "30.00") + @ExcelProperty("箱高度") + private BigDecimal height; + + @Schema(description = "尺寸单位 ID", example = "1") + private Long sizeUnitId; + + @Schema(description = "尺寸单位名称", example = "厘米") + @ExcelProperty("尺寸单位") + private String sizeUnitName; + + @Schema(description = "净重", example = "10.00") + @ExcelProperty("净重") + private BigDecimal netWeight; + + @Schema(description = "毛重", example = "12.00") + @ExcelProperty("毛重") + private BigDecimal grossWeight; + + @Schema(description = "重量单位 ID", example = "2") + private Long weightUnitId; + + @Schema(description = "重量单位名称", example = "千克") + @ExcelProperty("重量单位") + private String weightUnitName; + + @Schema(description = "检查员用户 ID", example = "1") + private Long inspectorUserId; + + @Schema(description = "检查员姓名", example = "张三") + @ExcelProperty("检查员") + private String inspectorName; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageSaveReqVO.java new file mode 100644 index 000000000..693595f92 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageSaveReqVO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 装箱单新增/修改 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 装箱单新增/修改 Request VO") +@Data +public class MesWmPackageSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "装箱单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "PKG20260307001") + @NotEmpty(message = "装箱单编号不能为空") + private String code; + + @Schema(description = "装箱日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "装箱日期不能为空") + private LocalDateTime packageDate; + + @Schema(description = "销售订单编号", example = "SO20260301") + private String salesOrderCode; + + @Schema(description = "发票编号", example = "INV20260301") + private String invoiceCode; + + @Schema(description = "客户 ID", example = "1") + private Long clientId; + + @Schema(description = "箱长度", example = "60.00") + private BigDecimal length; + + @Schema(description = "箱宽度", example = "40.00") + private BigDecimal width; + + @Schema(description = "箱高度", example = "30.00") + private BigDecimal height; + + @Schema(description = "尺寸单位 ID", example = "1") + private Long sizeUnitId; + + @Schema(description = "净重", example = "10.00") + private BigDecimal netWeight; + + @Schema(description = "毛重", example = "12.00") + private BigDecimal grossWeight; + + @Schema(description = "重量单位 ID", example = "2") + private Long weightUnitId; + + @Schema(description = "检查员用户 ID", example = "1") + private Long inspectorUserId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLinePageReqVO.java new file mode 100644 index 000000000..1c3c37af7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLinePageReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * MES 装箱明细分页 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 装箱明细分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmPackageLinePageReqVO extends PageParam { + + @Schema(description = "装箱单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "装箱单 ID 不能为空") + private Long packageId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineRespVO.java new file mode 100644 index 000000000..57330d03f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineRespVO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 装箱明细 Response VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 装箱明细 Response VO") +@Data +@Accessors(chain = true) +public class MesWmPackageLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "装箱单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long packageId; + + @Schema(description = "库存记录 ID", example = "1") + private Long materialStockId; + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "螺栓") + private String itemName; + + @Schema(description = "规格型号", example = "M10*50") + private String specification; + + @Schema(description = "计量单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "装箱数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal quantity; + + @Schema(description = "生产工单 ID", example = "1") + private Long workOrderId; + + @Schema(description = "生产工单编号", example = "WO20260301") + private String workOrderCode; + + @Schema(description = "批次号", example = "BATCH001") + private String batchCode; + + @Schema(description = "有效期") + private LocalDateTime expireDate; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineSaveReqVO.java new file mode 100644 index 000000000..5e257eeea --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineSaveReqVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 装箱明细新增/修改 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 装箱明细新增/修改 Request VO") +@Data +public class MesWmPackageLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "装箱单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "装箱单 ID 不能为空") + private Long packageId; + + @Schema(description = "库存记录 ID", example = "1") + private Long materialStockId; + + @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品物料不能为空") + private Long itemId; + + @Schema(description = "装箱数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "装箱数量不能为空") + @DecimalMin(value = "0.01", message = "装箱数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "生产工单 ID", example = "1") + private Long workOrderId; + + // DONE @AI:时间都是 LocalDateTIme; + @Schema(description = "有效期") + private LocalDateTime expireDate; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueController.java new file mode 100644 index 000000000..4836c4ac8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueController.java @@ -0,0 +1,182 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.productissue.vo.MesWmProductIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssueRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.productissue.MesWmProductIssueService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 领料出库单") +@RestController +@RequestMapping("/mes/wm/product-issue") +@Validated +public class MesWmProductIssueController { + + @Resource + private MesWmProductIssueService issueService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesMdClientService clientService; + + @PostMapping("/create") + @Operation(summary = "创建领料出库单") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:create')") + public CommonResult createProductIssue(@Valid @RequestBody MesWmProductIssueSaveReqVO createReqVO) { + return success(issueService.createProductIssue(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改领料出库单") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:update')") + public CommonResult updateProductIssue(@Valid @RequestBody MesWmProductIssueSaveReqVO updateReqVO) { + issueService.updateProductIssue(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除领料出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:delete')") + public CommonResult deleteProductIssue(@RequestParam("id") Long id) { + issueService.deleteProductIssue(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得领料出库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:query')") + public CommonResult getProductIssue(@RequestParam("id") Long id) { + MesWmProductIssueDO issue = issueService.getProductIssue(id); + if (issue == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(issue)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得领料出库单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:query')") + public CommonResult> getProductIssuePage( + @Valid MesWmProductIssuePageReqVO pageReqVO) { + PageResult pageResult = issueService.getProductIssuePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出领料出库单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportProductIssueExcel(@Valid MesWmProductIssuePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = issueService.getProductIssuePage(pageReqVO); + ExcelUtils.write(response, "领料出库单.xls", "数据", MesWmProductIssueRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/finish") + @Operation(summary = "完成领料出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:finish')") + public CommonResult finishProductIssue(@RequestParam("id") Long id) { + issueService.finishProductIssue(id); + return success(true); + } + + @PutMapping("/submit") + @Operation(summary = "提交领料出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:update')") + public CommonResult submitProductIssue(@RequestParam("id") Long id) { + issueService.submitProductIssue(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "执行拣货") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:update')") + public CommonResult stockProductIssue(@RequestParam("id") Long id) { + issueService.stockProductIssue(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消领料出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:update')") + public CommonResult cancelProductIssue(@RequestParam("id") Long id) { + issueService.cancelProductIssue(id); + return success(true); + } + + @GetMapping("/check-quantity") + @Operation(summary = "校验领料出库单数量", description = "校验每行明细数量之和是否等于行领料数量") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:query')") + public CommonResult checkProductIssueQuantity(@RequestParam("id") Long id) { + return success(issueService.checkProductIssueQuantity(id)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesWmProductIssueDO::getWorkstationId)); + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesWmProductIssueDO::getWorkOrderId)); + Map clientMap = clientService.getClientMap( + convertSet(workOrderMap.values(), MesProWorkOrderDO::getClientId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductIssueRespVO.class, vo -> { + MapUtils.findAndThen(workstationMap, vo.getWorkstationId(), + workstation -> vo.setWorkstationName(workstation.getName())); + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), workOrder -> { + vo.setWorkOrderCode(workOrder.getCode()); + MapUtils.findAndThen(clientMap, workOrder.getClientId(), client -> + vo.setClientCode(client.getCode()).setClientName(client.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueDetailController.java new file mode 100644 index 000000000..0d7a1aad1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueDetailController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.detail.MesWmProductIssueDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.detail.MesWmProductIssueDetailSaveReqVO; +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.wm.productissue.MesWmProductIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.productissue.MesWmProductIssueDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 领料出库明细") +@RestController +@RequestMapping("/mes/wm/product-issue-detail") +@Validated +public class MesWmProductIssueDetailController { + + @Resource + private MesWmProductIssueDetailService issueDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建领料出库明细") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:create')") + public CommonResult createProductIssueDetail(@Valid @RequestBody MesWmProductIssueDetailSaveReqVO createReqVO) { + return success(issueDetailService.createProductIssueDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改领料出库明细") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:update')") + public CommonResult updateProductIssueDetail(@Valid @RequestBody MesWmProductIssueDetailSaveReqVO updateReqVO) { + issueDetailService.updateProductIssueDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除领料出库明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:delete')") + public CommonResult deleteProductIssueDetail(@RequestParam("id") Long id) { + issueDetailService.deleteProductIssueDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得领料出库明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:query')") + public CommonResult getProductIssueDetail(@RequestParam("id") Long id) { + MesWmProductIssueDetailDO detail = issueDetailService.getProductIssueDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得领料出库明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:query')") + public CommonResult> getProductIssueDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = issueDetailService.getProductIssueDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmProductIssueDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmProductIssueDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmProductIssueDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmProductIssueDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductIssueDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueLineController.java new file mode 100644 index 000000000..e9b01d066 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/MesWmProductIssueLineController.java @@ -0,0 +1,124 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLineSaveReqVO; +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.wm.productissue.MesWmProductIssueLineDO; +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.wm.productissue.MesWmProductIssueLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 领料出库单行") +@RestController +@RequestMapping("/mes/wm/product-issue-line") +@Validated +public class MesWmProductIssueLineController { + + @Resource + private MesWmProductIssueLineService issueLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建领料出库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:create')") + public CommonResult createProductIssueLine(@Valid @RequestBody MesWmProductIssueLineSaveReqVO createReqVO) { + return success(issueLineService.createProductIssueLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改领料出库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:update')") + public CommonResult updateProductIssueLine(@Valid @RequestBody MesWmProductIssueLineSaveReqVO updateReqVO) { + issueLineService.updateProductIssueLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除领料出库单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:delete')") + public CommonResult deleteProductIssueLine(@RequestParam("id") Long id) { + issueLineService.deleteProductIssueLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得领料出库单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:query')") + public CommonResult getProductIssueLine(@RequestParam("id") Long id) { + MesWmProductIssueLineDO line = issueLineService.getProductIssueLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得领料出库单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:query')") + public CommonResult> getProductIssueLinePage( + @Valid MesWmProductIssueLinePageReqVO pageReqVO) { + PageResult pageResult = issueLineService.getProductIssueLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/list-by-issue") + @Operation(summary = "获得领料出库单行列表(按领料单编号)") + @Parameter(name = "issueId", description = "领料单编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-issue:query')") + public CommonResult> getProductIssueLineListByIssueId( + @RequestParam("issueId") Long issueId) { + List list = issueLineService.getProductIssueLineListByIssueId(issueId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmProductIssueLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductIssueLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssuePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssuePageReqVO.java new file mode 100644 index 000000000..4fafa9761 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssuePageReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 领料出库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmProductIssuePageReqVO extends PageParam { + + @Schema(description = "领料单编号", example = "ISSUE20250226001") + private String code; + + @Schema(description = "领料单名称", example = "生产领料") + private String name; + + @Schema(description = "工作站ID", example = "1") + private Long workstationId; + + @Schema(description = "生产工单ID", example = "1") + private Long workOrderId; + + @Schema(description = "生产任务ID", example = "1") + private Long taskId; + + @Schema(description = "客户ID", example = "1") + private Long clientId; + + @Schema(description = "状态", example = "10") + private Integer status; + + @Schema(description = "领料日期范围") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] issueDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssueRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssueRespVO.java new file mode 100644 index 000000000..355835038 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssueRespVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 领料出库单 Response VO") +@Data +public class MesWmProductIssueRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "领料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "ISSUE20250226001") + private String code; + + @Schema(description = "领料单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "生产领料") + private String name; + + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long workOrderId; + + @Schema(description = "生产工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "WO20250226001") + private String workOrderCode; + + @Schema(description = "工作站 ID", example = "1") + private Long workstationId; + + @Schema(description = "工作站名称", example = "装配工作站") + private String workstationName; + + @Schema(description = "客户编号", example = "C001") + private String clientCode; + + @Schema(description = "客户名称", example = "某某客户") + private String clientName; + + @Schema(description = "生产任务 ID", example = "1") + private Long taskId; + + @Schema(description = "领料日期") + private LocalDateTime issueDate; + + @Schema(description = "需求时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime requiredTime; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssueSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssueSaveReqVO.java new file mode 100644 index 000000000..7dbec278d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssueSaveReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 领料出库单新增/修改 Request VO") +@Data +public class MesWmProductIssueSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "领料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "ISSUE20250226001") + @NotBlank(message = "领料单编号不能为空") + private String code; + + @Schema(description = "领料单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "生产领料") + @NotBlank(message = "领料单名称不能为空") + private String name; + + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "生产工单 ID 不能为空") + private Long workOrderId; + + @Schema(description = "工作站 ID", example = "1") + private Long workstationId; + + @Schema(description = "需求时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "需求时间不能为空") + private LocalDateTime requiredTime; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailRespVO.java new file mode 100644 index 000000000..601d3939a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailRespVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 领料出库明细 Response VO") +@Data +public class MesWmProductIssueDetailRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "领料单编号", example = "1") + private Long issueId; + + @Schema(description = "行编号", example = "1") + private Long lineId; + + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + private String itemCode; + + @Schema(description = "物料名称", example = "螺丝") + private String itemName; + + @Schema(description = "规格型号", example = "M8*20") + private String specification; + + @Schema(description = "计量单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "领料数量", example = "300.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原材料仓库") + private String warehouseName; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A区") + private String locationName; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A01") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java new file mode 100644 index 000000000..de2a2b962 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 领料出库明细新增/修改 Request VO") +@Data +public class MesWmProductIssueDetailSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "领料单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "领料单行编号不能为空") + private Long lineId; + + @Schema(description = "领料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "领料单编号不能为空") + private Long issueId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "领料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") + @NotNull(message = "领料数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "领料数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLinePageReqVO.java new file mode 100644 index 000000000..c5ca6c5f5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 领料出库单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmProductIssueLinePageReqVO extends PageParam { + + @Schema(description = "领料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "领料单编号不能为空") + private Long issueId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineRespVO.java new file mode 100644 index 000000000..f21b4b73c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineRespVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 领料出库单行 Response VO") +@Data +public class MesWmProductIssueLineRespVO { + + @Schema(description = "行ID", example = "1") + private Long id; + + @Schema(description = "领料单ID", example = "1") + private Long issueId; + + @Schema(description = "物料ID", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "领料数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineSaveReqVO.java new file mode 100644 index 000000000..314b2b42d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/line/MesWmProductIssueLineSaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 领料出库单行 Save Request VO") +@Data +public class MesWmProductIssueLineSaveReqVO { + + @Schema(description = "行ID", example = "1") + private Long id; + + @Schema(description = "领料单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "领料单ID不能为空") + private Long issueId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料ID不能为空") + private Long itemId; + + @Schema(description = "领料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "领料数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "领料数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/MesWmProductProduceLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/MesWmProductProduceLineController.java new file mode 100644 index 000000000..9d663b584 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/MesWmProductProduceLineController.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productproduce; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productproduce.vo.MesWmProductProduceLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productproduce.vo.MesWmProductProduceLineRespVO; +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.wm.productproduce.MesWmProductProduceLineDO; +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.wm.productproduce.MesWmProductProduceLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 生产入库单行") +@RestController +@RequestMapping("/mes/wm/product-produce-line") +@Validated +public class MesWmProductProduceLineController { + + @Resource + private MesWmProductProduceLineService productProduceLineService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @GetMapping("/page") + @Operation(summary = "获得生产入库单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-product-produce:query')") + public CommonResult> getProductProduceLinePage( + @Valid MesWmProductProduceLinePageReqVO pageReqVO) { + PageResult pageResult = productProduceLineService.getProductProduceLinePage( + pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmProductProduceLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductProduceLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/vo/MesWmProductProduceLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/vo/MesWmProductProduceLinePageReqVO.java new file mode 100644 index 000000000..6d26b8af6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/vo/MesWmProductProduceLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productproduce.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 生产入库单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmProductProduceLinePageReqVO extends PageParam { + + @Schema(description = "报工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "报工单编号不能为空") + private Long feedbackId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/vo/MesWmProductProduceLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/vo/MesWmProductProduceLineRespVO.java new file mode 100644 index 000000000..7e41eed95 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productproduce/vo/MesWmProductProduceLineRespVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productproduce.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产入库单行 Response VO") +@Data +public class MesWmProductProduceLineRespVO { + + @Schema(description = "行ID", example = "1") + private Long id; + + @Schema(description = "入库单ID", example = "1") + private Long produceId; + + @Schema(description = "报工单 ID", example = "1") + private Long feedbackId; + + @Schema(description = "物料ID", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "入库数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "有效期") + private LocalDateTime expireDate; + + @Schema(description = "批号", example = "LOT001") + private String lotNumber; + + @Schema(description = "质检状态", example = "1") + private Integer qualityStatus; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptController.java new file mode 100644 index 000000000..62ce33f25 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptController.java @@ -0,0 +1,185 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.productreceipt.vo.MesWmProductReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptSaveReqVO; +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.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDO; +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.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.productreceipt.MesWmProductReceiptService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 产品收货单") +@RestController +@RequestMapping("/mes/wm/product-receipt") +@Validated +public class MesWmProductReceiptController { + + @Resource + private MesWmProductReceiptService productReceiptService; + + @Resource + private MesProWorkOrderService workOrderService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建产品收货单") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:create')") + public CommonResult createProductReceipt(@Valid @RequestBody MesWmProductReceiptSaveReqVO createReqVO) { + return success(productReceiptService.createProductReceipt(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改产品收货单") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:update')") + public CommonResult updateProductReceipt(@Valid @RequestBody MesWmProductReceiptSaveReqVO updateReqVO) { + productReceiptService.updateProductReceipt(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品收货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:delete')") + public CommonResult deleteProductReceipt(@RequestParam("id") Long id) { + productReceiptService.deleteProductReceipt(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品收货单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:query')") + public CommonResult getProductReceipt(@RequestParam("id") Long id) { + MesWmProductReceiptDO receipt = productReceiptService.getProductReceipt(id); + if (receipt == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(receipt)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品收货单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:query')") + public CommonResult> getProductReceiptPage( + @Valid MesWmProductReceiptPageReqVO pageReqVO) { + PageResult pageResult = productReceiptService.getProductReceiptPage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品收货单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportProductReceiptExcel(@Valid MesWmProductReceiptPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = productReceiptService.getProductReceiptPage(pageReqVO); + ExcelUtils.write(response, "产品收货单.xls", "数据", MesWmProductReceiptRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交产品收货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:update')") + public CommonResult submitProductReceipt(@RequestParam("id") Long id) { + productReceiptService.submitProductReceipt(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "执行上架") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:update')") + public CommonResult stockProductReceipt(@RequestParam("id") Long id) { + productReceiptService.stockProductReceipt(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "执行入库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:finish')") + public CommonResult finishProductReceipt(@RequestParam("id") Long id) { + productReceiptService.finishProductReceipt(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消产品收货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:update')") + public CommonResult cancelProductReceipt(@RequestParam("id") Long id) { + productReceiptService.cancelProductReceipt(id); + return success(true); + } + + @GetMapping("/check-quantity") + @Operation(summary = "校验产品收货单明细数量") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:query')") + public CommonResult checkProductReceiptQuantity(@RequestParam("id") Long id) { + return success(productReceiptService.checkProductReceiptQuantity(id)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesWmProductReceiptDO::getWorkOrderId)); + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmProductReceiptDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductReceiptRespVO.class, vo -> { + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), + workOrder -> vo.setWorkOrderCode(workOrder.getCode())); + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptDetailController.java new file mode 100644 index 000000000..9b5b9b0eb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptDetailController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.detail.MesWmProductReceiptDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.detail.MesWmProductReceiptDetailSaveReqVO; +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.wm.productreceipt.MesWmProductReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.productreceipt.MesWmProductReceiptDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 产品收货单明细") +@RestController +@RequestMapping("/mes/wm/product-receipt-detail") +@Validated +public class MesWmProductReceiptDetailController { + + @Resource + private MesWmProductReceiptDetailService productReceiptDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建产品收货单明细") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:create')") + public CommonResult createProductReceiptDetail(@Valid @RequestBody MesWmProductReceiptDetailSaveReqVO createReqVO) { + return success(productReceiptDetailService.createProductReceiptDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改产品收货单明细") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:update')") + public CommonResult updateProductReceiptDetail(@Valid @RequestBody MesWmProductReceiptDetailSaveReqVO updateReqVO) { + productReceiptDetailService.updateProductReceiptDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品收货单明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:delete')") + public CommonResult deleteProductReceiptDetail(@RequestParam("id") Long id) { + productReceiptDetailService.deleteProductReceiptDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品收货单明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:query')") + public CommonResult getProductReceiptDetail(@RequestParam("id") Long id) { + MesWmProductReceiptDetailDO detail = productReceiptDetailService.getProductReceiptDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得产品收货单明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:query')") + public CommonResult> getProductReceiptDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = productReceiptDetailService.getProductReceiptDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmProductReceiptDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmProductReceiptDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmProductReceiptDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmProductReceiptDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductReceiptDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptLineController.java new file mode 100644 index 000000000..a4b969dd4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/MesWmProductReceiptLineController.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line.MesWmProductReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line.MesWmProductReceiptLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line.MesWmProductReceiptLineSaveReqVO; +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.wm.productreceipt.MesWmProductReceiptLineDO; +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.wm.productreceipt.MesWmProductReceiptLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 产品收货单行") +@RestController +@RequestMapping("/mes/wm/product-receipt-line") +@Validated +public class MesWmProductReceiptLineController { + + @Resource + private MesWmProductReceiptLineService productReceiptLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建产品收货单行") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:create')") + public CommonResult createProductReceiptLine(@Valid @RequestBody MesWmProductReceiptLineSaveReqVO createReqVO) { + return success(productReceiptLineService.createProductReceiptLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改产品收货单行") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:update')") + public CommonResult updateProductReceiptLine(@Valid @RequestBody MesWmProductReceiptLineSaveReqVO updateReqVO) { + productReceiptLineService.updateProductReceiptLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品收货单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:delete')") + public CommonResult deleteProductReceiptLine(@RequestParam("id") Long id) { + productReceiptLineService.deleteProductReceiptLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品收货单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:query')") + public CommonResult getProductReceiptLine(@RequestParam("id") Long id) { + MesWmProductReceiptLineDO line = productReceiptLineService.getProductReceiptLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品收货单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-product-receipt:query')") + public CommonResult> getProductReceiptLinePage( + @Valid MesWmProductReceiptLinePageReqVO pageReqVO) { + PageResult pageResult = productReceiptLineService.getProductReceiptLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmProductReceiptLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductReceiptLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptPageReqVO.java new file mode 100644 index 000000000..27cdeef52 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 产品收货单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmProductReceiptPageReqVO extends PageParam { + + @Schema(description = "收货单编码", example = "PR202603010001") + private String code; + + @Schema(description = "收货单名称", example = "产品收货单-工单001") + private String name; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "产品物料编号", example = "1") + private Long itemId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptRespVO.java new file mode 100644 index 000000000..617bde92b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptRespVO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 产品收货单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmProductReceiptRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "收货单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PR202603010001") + @ExcelProperty("收货单编码") + private String code; + + @Schema(description = "收货单名称", example = "产品收货单-工单001") + @ExcelProperty("收货单名称") + private String name; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "生产工单编码", example = "WO202603010001") + @ExcelProperty("生产工单") + private String workOrderCode; + + @Schema(description = "产品物料编号", example = "1") + private Long itemId; + + @Schema(description = "产品物料编码", example = "P001") + @ExcelProperty("产品物料编码") + private String itemCode; + + @Schema(description = "产品物料名称", example = "成品A") + @ExcelProperty("产品物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "标准型") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "计量单位名称", example = "件") + @ExcelProperty("计量单位") + private String unitMeasureName; + + @Schema(description = "收货日期") + @ExcelProperty("收货日期") + private LocalDateTime receiptDate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptSaveReqVO.java new file mode 100644 index 000000000..19d8e347d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptSaveReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 产品收货单新增/修改 Request VO") +@Data +public class MesWmProductReceiptSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "收货单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PR202603010001") + @NotEmpty(message = "收货单编码不能为空") + private String code; + + @Schema(description = "收货单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品收货单-工单001") + @NotEmpty(message = "收货单名称不能为空") + private String name; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "收货日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "收货日期不能为空") + private LocalDateTime receiptDate; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/detail/MesWmProductReceiptDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/detail/MesWmProductReceiptDetailRespVO.java new file mode 100644 index 000000000..1bbff035c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/detail/MesWmProductReceiptDetailRespVO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 产品收货单明细 Response VO") +@Data +public class MesWmProductReceiptDetailRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "收货单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long lineId; + + @Schema(description = "收货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "P001") + private String itemCode; + + @Schema(description = "物料名称", example = "成品A") + private String itemName; + + @Schema(description = "规格型号", example = "标准型") + private String specification; + + @Schema(description = "计量单位名称", example = "件") + private String unitMeasureName; + + @Schema(description = "上架数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "成品仓") + private String warehouseName; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A区") + private String locationName; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A-01") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/detail/MesWmProductReceiptDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/detail/MesWmProductReceiptDetailSaveReqVO.java new file mode 100644 index 000000000..5b645f4d3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/detail/MesWmProductReceiptDetailSaveReqVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 产品收货单明细新增/修改 Request VO") +@Data +public class MesWmProductReceiptDetailSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "收货单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "收货单行编号不能为空") + private Long lineId; + + @Schema(description = "收货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "收货单编号不能为空") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "上架数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "上架数量不能为空") + @Positive(message = "上架数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLinePageReqVO.java new file mode 100644 index 000000000..c53937645 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLinePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 产品收货单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmProductReceiptLinePageReqVO extends PageParam { + + @Schema(description = "收货单编号", example = "1") + private Long receiptId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineRespVO.java new file mode 100644 index 000000000..7c1177fbc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineRespVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 产品收货单行 Response VO") +@Data +public class MesWmProductReceiptLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "收货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "库存物资记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "物料编码", example = "P001") + private String itemCode; + + @Schema(description = "物料名称", example = "成品A") + private String itemName; + + @Schema(description = "规格型号", example = "标准型") + private String specification; + + @Schema(description = "计量单位名称", example = "件") + private String unitMeasureName; + + @Schema(description = "收货数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260301001") + private String batchCode; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineSaveReqVO.java new file mode 100644 index 000000000..86d133d99 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineSaveReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 产品收货单行新增/修改 Request VO") +@Data +public class MesWmProductReceiptLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "收货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "收货单编号不能为空") + private Long receiptId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "库存物资记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "收货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "收货数量不能为空") + @Positive(message = "收货数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260301001") + private String batchCode; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesController.java new file mode 100644 index 000000000..f50624dd1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesController.java @@ -0,0 +1,181 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.productsales.vo.MesWmProductSalesPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService; +import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +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.convertSet; + +@Tag(name = "管理后台 - MES 销售出库单") +@RestController +@RequestMapping("/mes/wm/product-sales") +@Validated +public class MesWmProductSalesController { + + @Resource + private MesWmProductSalesService productSalesService; + + @Resource + private MesMdClientService clientService; + @Resource + private MesWmSalesNoticeService salesNoticeService; + + @PostMapping("/create") + @Operation(summary = "创建销售出库单") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:create')") + public CommonResult createProductSales(@Valid @RequestBody MesWmProductSalesSaveReqVO createReqVO) { + return success(productSalesService.createProductSales(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改销售出库单") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:update')") + public CommonResult updateProductSales(@Valid @RequestBody MesWmProductSalesSaveReqVO updateReqVO) { + productSalesService.updateProductSales(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:delete')") + public CommonResult deleteProductSales(@RequestParam("id") Long id) { + productSalesService.deleteProductSales(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售出库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:query')") + public CommonResult getProductSales(@RequestParam("id") Long id) { + MesWmProductSalesDO sales = productSalesService.getProductSales(id); + if (sales == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(sales)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得销售出库单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:query')") + public CommonResult> getProductSalesPage( + @Valid MesWmProductSalesPageReqVO pageReqVO) { + PageResult pageResult = productSalesService.getProductSalesPage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出销售出库单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportProductSalesExcel(@Valid MesWmProductSalesPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = productSalesService.getProductSalesPage(pageReqVO); + ExcelUtils.write(response, "销售出库单.xls", "数据", MesWmProductSalesRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交销售出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:submit')") + public CommonResult submitProductSales(@RequestParam("id") Long id) { + productSalesService.submitProductSales(id); + return success(true); + } + + @GetMapping("/check-quantity") + @Operation(summary = "校验销售出库单数量") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:query')") + public CommonResult checkProductSalesQuantity(@RequestParam("id") Long id) { + return success(productSalesService.checkProductSalesQuantity(id)); + } + + @PutMapping("/stock") + @Operation(summary = "执行拣货") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:stock')") + public CommonResult stockProductSales(@RequestParam("id") Long id) { + productSalesService.stockProductSales(id); + return success(true); + } + + @PutMapping("/shipping") + @Operation(summary = "填写运单") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:shipping')") + public CommonResult shippingProductSales(@Valid @RequestBody MesWmProductSalesShippingReqVO reqVO) { + productSalesService.shippingProductSales(reqVO); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "执行出库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:finish')") + public CommonResult finishProductSales(@RequestParam("id") Long id) { + productSalesService.finishProductSales(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消销售出库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:cancel')") + public CommonResult cancelProductSales(@RequestParam("id") Long id) { + productSalesService.cancelProductSales(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map clientMap = clientService.getClientMap( + convertSet(list, MesWmProductSalesDO::getClientId)); + Map noticeMap = salesNoticeService.getSalesNoticeMap( + convertSet(list, MesWmProductSalesDO::getNoticeId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductSalesRespVO.class, vo -> { + MapUtils.findAndThen(clientMap, vo.getClientId(), client -> + vo.setClientName(client.getName()).setClientCode(client.getCode())); + MapUtils.findAndThen(noticeMap, vo.getNoticeId(), + notice -> vo.setNoticeCode(notice.getNoticeCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesDetailController.java new file mode 100644 index 000000000..4c05d8aa6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesDetailController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail.MesWmProductSalesDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail.MesWmProductSalesDetailSaveReqVO; +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.wm.productsales.MesWmProductSalesDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.productsales.MesWmProductSalesDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 销售出库明细") +@RestController +@RequestMapping("/mes/wm/product-sales-detail") +@Validated +public class MesWmProductSalesDetailController { + + @Resource + private MesWmProductSalesDetailService productSalesDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建销售出库明细") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:create')") + public CommonResult createProductSalesDetail(@Valid @RequestBody MesWmProductSalesDetailSaveReqVO createReqVO) { + return success(productSalesDetailService.createProductSalesDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改销售出库明细") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:update')") + public CommonResult updateProductSalesDetail(@Valid @RequestBody MesWmProductSalesDetailSaveReqVO updateReqVO) { + productSalesDetailService.updateProductSalesDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售出库明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:delete')") + public CommonResult deleteProductSalesDetail(@RequestParam("id") Long id) { + productSalesDetailService.deleteProductSalesDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售出库明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:query')") + public CommonResult getProductSalesDetail(@RequestParam("id") Long id) { + MesWmProductSalesDetailDO detail = productSalesDetailService.getProductSalesDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得销售出库明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:query')") + public CommonResult> getProductSalesDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = productSalesDetailService.getProductSalesDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmProductSalesDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmProductSalesDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmProductSalesDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmProductSalesDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductSalesDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesLineController.java new file mode 100644 index 000000000..e6196b2ac --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesLineController.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO; +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.wm.productsales.MesWmProductSalesLineDO; +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.wm.productsales.MesWmProductSalesLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 销售出库单行") +@RestController +@RequestMapping("/mes/wm/product-sales-line") +@Validated +public class MesWmProductSalesLineController { + + @Resource + private MesWmProductSalesLineService productSalesLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + + @PostMapping("/create") + @Operation(summary = "创建销售出库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:create')") + public CommonResult createProductSalesLine(@Valid @RequestBody MesWmProductSalesLineSaveReqVO createReqVO) { + return success(productSalesLineService.createProductSalesLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改销售出库单行") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:update')") + public CommonResult updateProductSalesLine(@Valid @RequestBody MesWmProductSalesLineSaveReqVO updateReqVO) { + productSalesLineService.updateProductSalesLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售出库单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:delete')") + public CommonResult deleteProductSalesLine(@RequestParam("id") Long id) { + productSalesLineService.deleteProductSalesLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售出库单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:query')") + public CommonResult getProductSalesLine(@RequestParam("id") Long id) { + MesWmProductSalesLineDO line = productSalesLineService.getProductSalesLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得销售出库单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-product-sales:query')") + public CommonResult> getProductSalesLinePage( + @Valid MesWmProductSalesLinePageReqVO pageReqVO) { + PageResult pageResult = productSalesLineService.getProductSalesLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmProductSalesLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmProductSalesLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesPageReqVO.java new file mode 100644 index 000000000..3f65810c8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 销售出库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmProductSalesPageReqVO extends PageParam { + + @Schema(description = "出库单号", example = "PS2026030001") + private String code; + + @Schema(description = "出库单名称", example = "产品出库单") + private String name; + + @Schema(description = "客户编号", example = "1") + private Long clientId; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "计划发货日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] shipmentDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesRespVO.java new file mode 100644 index 000000000..4d67b5e8c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesRespVO.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 销售出库单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmProductSalesRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "出库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "PS2026030001") + @ExcelProperty("出库单号") + private String code; + + @Schema(description = "出库单名称", example = "产品出库单") + @ExcelProperty("出库单名称") + private String name; + + @Schema(description = "客户ID", example = "1") + private Long clientId; + + @Schema(description = "客户名称", example = "某客户") + @ExcelProperty("客户") + private String clientName; + + @Schema(description = "销售订单号", example = "SO2026030001") + @ExcelProperty("销售订单号") + private String salesOrderCode; + + @Schema(description = "出库日期") + @ExcelProperty("出库日期") + private LocalDateTime salesDate; + + @Schema(description = "发货通知单ID", example = "1") + private Long noticeId; + + @Schema(description = "发货通知单编号", example = "SN2026030001") + @ExcelProperty("发货通知单编号") + private String noticeCode; + + @Schema(description = "客户编码", example = "C001") + @ExcelProperty("客户编码") + private String clientCode; + + @Schema(description = "收货人", example = "张三") + @ExcelProperty("收货人") + private String contactName; + + @Schema(description = "联系方式", example = "13800138000") + @ExcelProperty("联系方式") + private String contactTelephone; + + @Schema(description = "收货地址", example = "北京市朝阳区XX路XX号") + @ExcelProperty("收货地址") + private String contactAddress; + + @Schema(description = "承运商", example = "顺丰快递") + @ExcelProperty("承运商") + private String carrier; + + @Schema(description = "运输单号", example = "SF1234567890") + @ExcelProperty("运输单号") + private String shippingNumber; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesSaveReqVO.java new file mode 100644 index 000000000..1c94e1327 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesSaveReqVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 销售出库单新增/修改 Request VO") +@Data +public class MesWmProductSalesSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "出库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "PS2026030001") + @NotEmpty(message = "出库单号不能为空") + private String code; + + @Schema(description = "出库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "产品出库单") + @NotEmpty(message = "出库单名称不能为空") + private String name; + + @Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "客户不能为空") + private Long clientId; + + @Schema(description = "销售订单号", example = "SO2026030001") + private String salesOrderCode; + + @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出库日期不能为空") + private LocalDateTime salesDate; + + @Schema(description = "发货通知单ID", example = "1") + private Long noticeId; + + @Schema(description = "收货人", example = "张三") + private String contactName; + + @Schema(description = "联系方式", example = "13800138000") + private String contactTelephone; + + @Schema(description = "收货地址", example = "北京市朝阳区XX路XX号") + private String contactAddress; + + @Schema(description = "承运商", example = "顺丰快递") + private String carrier; + + @Schema(description = "运输单号", example = "SF1234567890") + private String shippingNumber; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesShippingReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesShippingReqVO.java new file mode 100644 index 000000000..c7bcbb43b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesShippingReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 销售出库单填写运单 Request VO") +@Data +public class MesWmProductSalesShippingReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "编号不能为空") + private Long id; + + @Schema(description = "承运商", example = "顺丰快递") + private String carrier; + + @Schema(description = "运输单号", example = "SF1234567890") + private String shippingNumber; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailPageReqVO.java new file mode 100644 index 000000000..ffb52f821 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 销售出库明细分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmProductSalesDetailPageReqVO extends PageParam { + + @Schema(description = "出库单ID", example = "1") + private Long salesId; + + @Schema(description = "出库单行ID", example = "1") + private Long lineId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailRespVO.java new file mode 100644 index 000000000..716f2cefd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailRespVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 销售出库明细 Response VO") +@Data +public class MesWmProductSalesDetailRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "出库单行ID", example = "1") + private Long lineId; + + @Schema(description = "出库单ID", example = "1") + private Long salesId; + + @Schema(description = "物料ID", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "产品A") + private String itemName; + + @Schema(description = "规格型号", example = "100g") + private String specification; + + @Schema(description = "单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "拣货数量", example = "50") + private BigDecimal quantity; + + @Schema(description = "库存记录ID", example = "1") + private Long materialStockId; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH001") + private String batchCode; + + @Schema(description = "仓库ID", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "成品仓") + private String warehouseName; + + @Schema(description = "库区ID", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A区") + private String locationName; + + @Schema(description = "库位ID", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A-01") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailSaveReqVO.java new file mode 100644 index 000000000..149784380 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/detail/MesWmProductSalesDetailSaveReqVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 销售出库明细新增/修改 Request VO") +@Data +public class MesWmProductSalesDetailSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "出库单行ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "出库单行ID不能为空") + private Long lineId; + + @Schema(description = "出库单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "出库单ID不能为空") + private Long salesId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料不能为空") + private Long itemId; + + @Schema(description = "拣货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") + @NotNull(message = "拣货数量不能为空") + private BigDecimal quantity; + + @Schema(description = "库存记录ID", example = "1") + private Long materialStockId; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH001") + private String batchCode; + + @Schema(description = "仓库ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库不能为空") + private Long warehouseId; + + @Schema(description = "库区ID", example = "1") + private Long locationId; + + @Schema(description = "库位ID", example = "1") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLinePageReqVO.java new file mode 100644 index 000000000..73b3df619 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLinePageReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +@Schema(description = "管理后台 - MES 销售出库单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmProductSalesLinePageReqVO extends PageParam { + + @Schema(description = "出库单ID", example = "1") + private Long salesId; + + @Schema(description = "客户编号", example = "1") + private Long clientId; + + @Schema(description = "出库单编号列表(内部使用,客户过滤时自动填充)", hidden = true) + private List salesIds; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java new file mode 100644 index 000000000..19eff6578 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 销售出库单行 Response VO") +@Data +public class MesWmProductSalesLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "出库单ID", example = "1") + private Long salesId; + + @Schema(description = "物料ID", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "产品A") + private String itemName; + + @Schema(description = "规格型号", example = "100g") + private String specification; + + @Schema(description = "单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "出库数量", example = "100") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "B20260301001") + private String batchCode; + + @Schema(description = "是否出厂检验", example = "true") + private Boolean oqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java new file mode 100644 index 000000000..444c2b8bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 销售出库单行新增/修改 Request VO") +@Data +public class MesWmProductSalesLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "出库单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "出库单ID不能为空") + private Long salesId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料不能为空") + private Long itemId; + + @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "出库数量不能为空") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "B20260301001") + private String batchCode; + + @Schema(description = "是否出厂检验", example = "true") + private Boolean oqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueController.java new file mode 100644 index 000000000..c58150364 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.returnissue.vo.MesWmReturnIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.MesWmReturnIssueRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.MesWmReturnIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDO; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 生产退料单") +@RestController +@RequestMapping("/mes/wm/return-issue") +@Validated +public class MesWmReturnIssueController { + + @Resource + private MesWmReturnIssueService issueService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesProWorkOrderService workOrderService; + + @PostMapping("/create") + @Operation(summary = "创建生产退料单") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:create')") + public CommonResult createReturnIssue(@Valid @RequestBody MesWmReturnIssueSaveReqVO createReqVO) { + return success(issueService.createReturnIssue(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改生产退料单") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:update')") + public CommonResult updateReturnIssue(@Valid @RequestBody MesWmReturnIssueSaveReqVO updateReqVO) { + issueService.updateReturnIssue(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产退料单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:delete')") + public CommonResult deleteReturnIssue(@RequestParam("id") Long id) { + issueService.deleteReturnIssue(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产退料单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:query')") + public CommonResult getReturnIssue(@RequestParam("id") Long id) { + MesWmReturnIssueDO issue = issueService.getReturnIssue(id); + if (issue == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(issue)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得生产退料单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:query')") + public CommonResult> getReturnIssuePage( + @Valid MesWmReturnIssuePageReqVO pageReqVO) { + PageResult pageResult = issueService.getReturnIssuePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出生产退料单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportReturnIssueExcel(@Valid MesWmReturnIssuePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = issueService.getReturnIssuePage(pageReqVO); + ExcelUtils.write(response, "生产退料单.xls", "数据", MesWmReturnIssueRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/finish") + @Operation(summary = "完成生产退料单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:finish')") + public CommonResult finishReturnIssue(@RequestParam("id") Long id) { + issueService.finishReturnIssue(id); + return success(true); + } + + @PutMapping("/submit") + @Operation(summary = "提交生产退料单(草稿 → 待检验/待上架)") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:update')") + public CommonResult submitReturnIssue(@RequestParam("id") Long id) { + issueService.submitReturnIssue(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "入库上架") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:update')") + public CommonResult stockReturnIssue(@RequestParam("id") Long id) { + issueService.stockReturnIssue(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消生产退料单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:update')") + public CommonResult cancelReturnIssue(@RequestParam("id") Long id) { + issueService.cancelReturnIssue(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map workstationMap = workstationService.getWorkstationMap( + convertSet(list, MesWmReturnIssueDO::getWorkstationId)); + Map workOrderMap = workOrderService.getWorkOrderMap( + convertSet(list, MesWmReturnIssueDO::getWorkOrderId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnIssueRespVO.class, vo -> { + MapUtils.findAndThen(workstationMap, vo.getWorkstationId(), + workstation -> vo.setWorkstationName(workstation.getName())); + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(), + workOrder -> vo.setWorkOrderCode(workOrder.getCode())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueDetailController.java new file mode 100644 index 000000000..642692c06 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueDetailController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.detail.MesWmReturnIssueDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.detail.MesWmReturnIssueDetailSaveReqVO; +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.wm.returnissue.MesWmReturnIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.returnissue.MesWmReturnIssueDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 生产退料明细") +@RestController +@RequestMapping("/mes/wm/return-issue-detail") +@Validated +public class MesWmReturnIssueDetailController { + + @Resource + private MesWmReturnIssueDetailService issueDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建生产退料明细") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:create')") + public CommonResult createReturnIssueDetail(@Valid @RequestBody MesWmReturnIssueDetailSaveReqVO createReqVO) { + return success(issueDetailService.createReturnIssueDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改生产退料明细") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:update')") + public CommonResult updateReturnIssueDetail(@Valid @RequestBody MesWmReturnIssueDetailSaveReqVO updateReqVO) { + issueDetailService.updateReturnIssueDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产退料明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:delete')") + public CommonResult deleteReturnIssueDetail(@RequestParam("id") Long id) { + issueDetailService.deleteReturnIssueDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产退料明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:query')") + public CommonResult getReturnIssueDetail(@RequestParam("id") Long id) { + MesWmReturnIssueDetailDO detail = issueDetailService.getReturnIssueDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得生产退料明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:query')") + public CommonResult> getReturnIssueDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = issueDetailService.getReturnIssueDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmReturnIssueDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmReturnIssueDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmReturnIssueDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmReturnIssueDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnIssueDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueLineController.java new file mode 100644 index 000000000..fcb3e89f2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/MesWmReturnIssueLineController.java @@ -0,0 +1,123 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWmReturnIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWmReturnIssueLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWmReturnIssueLineSaveReqVO; +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.wm.returnissue.MesWmReturnIssueLineDO; +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.wm.returnissue.MesWmReturnIssueLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 生产退料单行") +@RestController +@RequestMapping("/mes/wm/return-issue-line") +@Validated +public class MesWmReturnIssueLineController { + + @Resource + private MesWmReturnIssueLineService issueLineService; + + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建生产退料单行") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:create')") + public CommonResult createReturnIssueLine(@Valid @RequestBody MesWmReturnIssueLineSaveReqVO createReqVO) { + return success(issueLineService.createReturnIssueLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改生产退料单行") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:update')") + public CommonResult updateReturnIssueLine(@Valid @RequestBody MesWmReturnIssueLineSaveReqVO updateReqVO) { + issueLineService.updateReturnIssueLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除生产退料单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:delete')") + public CommonResult deleteReturnIssueLine(@RequestParam("id") Long id) { + issueLineService.deleteReturnIssueLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得生产退料单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:query')") + public CommonResult getReturnIssueLine(@RequestParam("id") Long id) { + MesWmReturnIssueLineDO line = issueLineService.getReturnIssueLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得生产退料单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:query')") + public CommonResult> getReturnIssueLinePage( + @Valid MesWmReturnIssueLinePageReqVO pageReqVO) { + PageResult pageResult = issueLineService.getReturnIssueLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/list-by-issue") + @Operation(summary = "获得生产退料单行列表(按退料单编号)") + @Parameter(name = "issueId", description = "退料单编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-issue:query')") + public CommonResult> getReturnIssueLineListByIssueId( + @RequestParam("issueId") Long issueId) { + List list = issueLineService.getReturnIssueLineListByIssueId(issueId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmReturnIssueLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnIssueLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssuePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssuePageReqVO.java new file mode 100644 index 000000000..c27eca8fa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssuePageReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Schema(description = "管理后台 - MES 生产退料单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmReturnIssuePageReqVO extends PageParam { + + @Schema(description = "退料单编号", example = "RI20250226001") + private String code; + + @Schema(description = "退料单名称", example = "生产退料") + private String name; + + @Schema(description = "工作站 ID", example = "1") + private Long workstationId; + + @Schema(description = "生产工单 ID", example = "1") + private Long workOrderId; + + @Schema(description = "退料类型", example = "1") + private Integer type; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssueRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssueRespVO.java new file mode 100644 index 000000000..5650522b9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssueRespVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产退料单 Response VO") +@Data +public class MesWmReturnIssueRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "退料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RI20250226001") + private String code; + + @Schema(description = "退料单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "生产退料") + private String name; + + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long workOrderId; + + @Schema(description = "生产工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "WO20250226001") + private String workOrderCode; + + @Schema(description = "工作站 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long workstationId; + + @Schema(description = "工作站名称", example = "装配工作站") + private String workstationName; + + @Schema(description = "退料类型", example = "1") + private Integer type; + + @Schema(description = "退料日期") + private LocalDateTime returnDate; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssueSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssueSaveReqVO.java new file mode 100644 index 000000000..3ad2d5c20 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssueSaveReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产退料单新增/修改 Request VO") +@Data +public class MesWmReturnIssueSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "退料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RI20250226001") + @NotBlank(message = "退料单编号不能为空") + private String code; + + @Schema(description = "退料单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "生产退料") + @NotBlank(message = "退料单名称不能为空") + private String name; + + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "生产工单 ID 不能为空") + private Long workOrderId; + + @Schema(description = "工作站 ID", example = "1") + private Long workstationId; + + @Schema(description = "退料类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退料类型不能为空") + private Integer type; + + @Schema(description = "退料日期") + private LocalDateTime returnDate; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailRespVO.java new file mode 100644 index 000000000..cfaa84471 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailRespVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产退料明细 Response VO") +@Data +public class MesWmReturnIssueDetailRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "退料单编号", example = "1") + private Long issueId; + + @Schema(description = "行编号", example = "1") + private Long lineId; + + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + private String itemCode; + + @Schema(description = "物料名称", example = "螺丝") + private String itemName; + + @Schema(description = "规格型号", example = "M8*20") + private String specification; + + @Schema(description = "计量单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "退料数量", example = "300.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原材料仓库") + private String warehouseName; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A区") + private String locationName; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A01") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java new file mode 100644 index 000000000..6659bf498 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 生产退料明细新增/修改 Request VO") +@Data +public class MesWmReturnIssueDetailSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "退料单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退料单行编号不能为空") + private Long lineId; + + @Schema(description = "退料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退料单编号不能为空") + private Long issueId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "退料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") + @NotNull(message = "退料数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "退料数量必须大于0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库区编号不能为空") + private Long locationId; + + @Schema(description = "库位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库位编号不能为空") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLinePageReqVO.java new file mode 100644 index 000000000..065132b3b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 生产退料单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmReturnIssueLinePageReqVO extends PageParam { + + @Schema(description = "退料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退料单编号不能为空") + private Long issueId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLineRespVO.java new file mode 100644 index 000000000..ccbe46b2e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLineRespVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 生产退料单行 Response VO") +@Data +public class MesWmReturnIssueLineRespVO { + + @Schema(description = "行 ID", example = "1") + private Long id; + + @Schema(description = "退料单 ID", example = "1") + private Long issueId; + + @Schema(description = "物料 ID", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "库存记录 ID", example = "1") + private Long materialStockId; + + @Schema(description = "退料数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次 ID", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "BAT202601001") + private String batchCode; + + @Schema(description = "是否需要质检", example = "false") + private Boolean rqcCheckFlag; + + @Schema(description = "质量状态", example = "0") + private Integer qualityStatus; + + @Schema(description = "退货检验单 ID", example = "21601") + private Long rqcId; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLineSaveReqVO.java new file mode 100644 index 000000000..3403b2abd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/line/MesWmReturnIssueLineSaveReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 生产退料单行 Save Request VO") +@Data +public class MesWmReturnIssueLineSaveReqVO { + + @Schema(description = "行 ID", example = "1") + private Long id; + + @Schema(description = "退料单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退料单 ID 不能为空") + private Long issueId; + + @Schema(description = "物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料 ID 不能为空") + private Long itemId; + + @Schema(description = "退料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "退料数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "退料数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "库存记录 ID", example = "1") + private Long materialStockId; + + @Schema(description = "批次 ID", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "BCH20260330001") + private String batchCode; + + @Schema(description = "是否需要质检", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "是否需要质检不能为空") + private Boolean rqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesController.java new file mode 100644 index 000000000..d765f69da --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesController.java @@ -0,0 +1,169 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.returnsales.vo.MesWmReturnSalesPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +/** + * 管理后台 - MES 销售退货单 Controller + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 销售退货单") +@RestController +@RequestMapping("/mes/wm/return-sales") +@Validated +public class MesWmReturnSalesController { + + @Resource + private MesWmReturnSalesService returnSalesService; + @Resource + private MesMdClientService clientService; + + @PostMapping("/create") + @Operation(summary = "创建销售退货单") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:create')") + public CommonResult createReturnSales(@Valid @RequestBody MesWmReturnSalesSaveReqVO createReqVO) { + return success(returnSalesService.createReturnSales(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改销售退货单") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:update')") + public CommonResult updateReturnSales(@Valid @RequestBody MesWmReturnSalesSaveReqVO updateReqVO) { + returnSalesService.updateReturnSales(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售退货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:delete')") + public CommonResult deleteReturnSales(@RequestParam("id") Long id) { + returnSalesService.deleteReturnSales(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售退货单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") + public CommonResult getReturnSales(@RequestParam("id") Long id) { + MesWmReturnSalesDO returnSales = returnSalesService.getReturnSales(id); + if (returnSales == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(returnSales)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得销售退货单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") + public CommonResult> getReturnSalesPage( + @Valid MesWmReturnSalesPageReqVO pageReqVO) { + PageResult pageResult = returnSalesService.getReturnSalesPage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出销售退货单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportReturnSalesExcel(@Valid MesWmReturnSalesPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = returnSalesService.getReturnSalesPage(pageReqVO); + ExcelUtils.write(response, "销售退货单.xls", "数据", MesWmReturnSalesRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交销售退货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:submit')") + public CommonResult submitReturnSales(@RequestParam("id") Long id) { + returnSalesService.submitReturnSales(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "执行退货") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:finish')") + public CommonResult finishReturnSales(@RequestParam("id") Long id) { + returnSalesService.finishReturnSales(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "执行上架") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:stock')") + public CommonResult stockReturnSales(@RequestParam("id") Long id) { + returnSalesService.stockReturnSales(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消销售退货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:cancel')") + public CommonResult cancelReturnSales(@RequestParam("id") Long id) { + returnSalesService.cancelReturnSales(id); + return success(true); + } + + @GetMapping("/check-quantity") + @Operation(summary = "校验销售退货单数量", description = "校验每行明细数量之和是否等于行退货数量") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") + public CommonResult checkReturnSalesQuantity(@RequestParam("id") Long id) { + return success(returnSalesService.checkReturnSalesQuantity(id)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map clientMap = clientService.getClientMap( + convertSet(list, MesWmReturnSalesDO::getClientId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnSalesRespVO.class, vo -> + MapUtils.findAndThen(clientMap, vo.getClientId(), client -> + vo.setClientCode(client.getCode()).setClientName(client.getName()).setClientNickname(client.getNickname()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesDetailController.java new file mode 100644 index 000000000..83a550c7e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesDetailController.java @@ -0,0 +1,148 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail.MesWmReturnSalesDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail.MesWmReturnSalesDetailSaveReqVO; +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.wm.returnsales.MesWmReturnSalesDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.returnsales.MesWmReturnSalesDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 销售退货明细") +@RestController +@RequestMapping("/mes/wm/return-sales-detail") +@Validated +public class MesWmReturnSalesDetailController { + + @Resource + private MesWmReturnSalesDetailService returnSalesDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建销售退货明细") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:create')") + public CommonResult createReturnSalesDetail(@Valid @RequestBody MesWmReturnSalesDetailSaveReqVO createReqVO) { + return success(returnSalesDetailService.createReturnSalesDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改销售退货明细") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:update')") + public CommonResult updateReturnSalesDetail(@Valid @RequestBody MesWmReturnSalesDetailSaveReqVO updateReqVO) { + returnSalesDetailService.updateReturnSalesDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售退货明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:delete')") + public CommonResult deleteReturnSalesDetail(@RequestParam("id") Long id) { + returnSalesDetailService.deleteReturnSalesDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售退货明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") + public CommonResult getReturnSalesDetail(@RequestParam("id") Long id) { + MesWmReturnSalesDetailDO detail = returnSalesDetailService.getReturnSalesDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得销售退货明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") + public CommonResult> getReturnSalesDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = returnSalesDetailService.getReturnSalesDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmReturnSalesDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmReturnSalesDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmReturnSalesDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmReturnSalesDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnSalesDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setItemUnit(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> + vo.setWarehouseCode(warehouse.getCode()).setWarehouseName(warehouse.getName()) + ); + MapUtils.findAndThen(locationMap, vo.getLocationId(), location -> + vo.setLocationCode(location.getCode()).setLocationName(location.getName()) + ); + MapUtils.findAndThen(areaMap, vo.getAreaId(), area -> + vo.setAreaCode(area.getCode()).setAreaName(area.getName()) + ); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesLineController.java new file mode 100644 index 000000000..cf6689542 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/MesWmReturnSalesLineController.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLineSaveReqVO; +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.wm.returnsales.MesWmReturnSalesLineDO; +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.wm.returnsales.MesWmReturnSalesLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Tag(name = "管理后台 - MES 销售退货单行") +@RestController +@RequestMapping("/mes/wm/return-sales-line") +@Validated +public class MesWmReturnSalesLineController { + + @Resource + private MesWmReturnSalesLineService returnSalesLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建销售退货单行") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:create')") + public CommonResult createReturnSalesLine(@Valid @RequestBody MesWmReturnSalesLineSaveReqVO createReqVO) { + return success(returnSalesLineService.createReturnSalesLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改销售退货单行") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:update')") + public CommonResult updateReturnSalesLine(@Valid @RequestBody MesWmReturnSalesLineSaveReqVO updateReqVO) { + returnSalesLineService.updateReturnSalesLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售退货单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:delete')") + public CommonResult deleteReturnSalesLine(@RequestParam("id") Long id) { + returnSalesLineService.deleteReturnSalesLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售退货单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") + public CommonResult getReturnSalesLine(@RequestParam("id") Long id) { + MesWmReturnSalesLineDO line = returnSalesLineService.getReturnSalesLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得销售退货单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") + public CommonResult> getReturnSalesLinePage( + @Valid MesWmReturnSalesLinePageReqVO pageReqVO) { + PageResult pageResult = returnSalesLineService.getReturnSalesLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/list-by-return-sales") + @Operation(summary = "获得销售退货单行列表(按退货单编号)") + @Parameter(name = "returnId", description = "退货单编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-sales:query')") + public CommonResult> getReturnSalesLineListByReturnId( + @RequestParam("returnId") Long returnId) { + List list = returnSalesLineService.getReturnSalesLineListByReturnId(returnId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmReturnSalesLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnSalesLineRespVO.class, vo -> + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setItemUnit(unitMeasure.getName())); + })); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesPageReqVO.java new file mode 100644 index 000000000..17ef39ac1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesPageReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmReturnSalesPageReqVO extends PageParam { + + @Schema(description = "退货单编号", example = "RS202603010001") + private String code; + + @Schema(description = "退货单名称", example = "销售退货") + private String name; + + @Schema(description = "销售订单编号", example = "SO202603010001") + private String salesOrderCode; + + @Schema(description = "客户 ID", example = "1") + private Long clientId; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "退货日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesRespVO.java new file mode 100644 index 000000000..c2f11b0ee --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesRespVO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货单 Response VO") +@Data +public class MesWmReturnSalesRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RS202603010001") + private String code; + + @Schema(description = "退货单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "销售退货") + private String name; + + @Schema(description = "销售订单编号", example = "SO202603010001") + private String salesOrderCode; + + @Schema(description = "客户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long clientId; + + @Schema(description = "客户编码", example = "C001") + private String clientCode; + + @Schema(description = "客户名称", example = "XX客户") + private String clientName; + + @Schema(description = "客户简称", example = "XX") + private String clientNickname; + + @Schema(description = "退货日期") + private LocalDateTime returnDate; + + @Schema(description = "退货原因", example = "质量问题") + private String returnReason; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesSaveReqVO.java new file mode 100644 index 000000000..15caf1f3c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesSaveReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 管理后台 - MES 销售退货单新增/修改 Request VO + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货单新增/修改 Request VO") +@Data +public class MesWmReturnSalesSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RS202603010001") + @NotBlank(message = "退货单编号不能为空") + private String code; + + @Schema(description = "退货单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "销售退货") + @NotBlank(message = "退货单名称不能为空") + private String name; + + @Schema(description = "销售订单编号", example = "SO202603010001") + private String salesOrderCode; + + @Schema(description = "客户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "客户 ID 不能为空") + private Long clientId; + + @Schema(description = "退货日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "退货日期不能为空") + private LocalDateTime returnDate; + + @Schema(description = "退货原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "质量问题") + @NotBlank(message = "退货原因不能为空") + private String returnReason; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailPageReqVO.java new file mode 100644 index 000000000..1db1faae6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货明细分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmReturnSalesDetailPageReqVO extends PageParam { + + @Schema(description = "退货单ID", example = "1") + private Long returnId; + + @Schema(description = "行ID", example = "1") + private Long lineId; + + @Schema(description = "物料ID", example = "1") + private Long itemId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailRespVO.java new file mode 100644 index 000000000..8f9693b72 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailRespVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货明细 Response VO") +@Data +public class MesWmReturnSalesDetailRespVO { + + @Schema(description = "明细ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "退货单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long returnId; + + @Schema(description = "行ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long lineId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "物料A") + private String itemName; + + @Schema(description = "物料规格", example = "100*200") + private String itemSpecification; + + @Schema(description = "计量单位", example = "个") + private String itemUnit; + + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "B001") + private String batchCode; + + @Schema(description = "仓库ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long warehouseId; + + @Schema(description = "仓库编码", example = "WH001") + private String warehouseCode; + + @Schema(description = "仓库名称", example = "仓库A") + private String warehouseName; + + @Schema(description = "库区ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long locationId; + + @Schema(description = "库区编码", example = "LOC001") + private String locationCode; + + @Schema(description = "库区名称", example = "库区A") + private String locationName; + + @Schema(description = "库位ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long areaId; + + @Schema(description = "库位编码", example = "AREA001") + private String areaCode; + + @Schema(description = "库位名称", example = "库位A") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailSaveReqVO.java new file mode 100644 index 000000000..7991a82bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailSaveReqVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货明细新增/修改 Request VO") +@Data +public class MesWmReturnSalesDetailSaveReqVO { + + @Schema(description = "明细ID", example = "1") + private Long id; + + @Schema(description = "退货单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退货单ID不能为空") + private Long returnId; + + @Schema(description = "行ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "行ID不能为空") + private Long lineId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料ID不能为空") + private Long itemId; + + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "仓库ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库ID不能为空") + private Long warehouseId; + + @Schema(description = "库区ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库区ID不能为空") + private Long locationId; + + @Schema(description = "库位ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库位ID不能为空") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLinePageReqVO.java new file mode 100644 index 000000000..838cd7e2b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLinePageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmReturnSalesLinePageReqVO extends PageParam { + + @Schema(description = "退货单ID", example = "1") + private Long returnId; + + @Schema(description = "物料ID", example = "1") + private Long itemId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineRespVO.java new file mode 100644 index 000000000..cb07a4468 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineRespVO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货单行 Response VO") +@Data +public class MesWmReturnSalesLineRespVO { + + @Schema(description = "行ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "退货单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long returnId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "物料A") + private String itemName; + + @Schema(description = "物料规格", example = "100*200") + private String itemSpecification; + + @Schema(description = "计量单位", example = "个") + private String itemUnit; + + @Schema(description = "退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "退货检验单 ID", example = "400") + private Long rqcId; + + @Schema(description = "是否需要质检", example = "true") + private Boolean rqcCheckFlag; + + @Schema(description = "批次号", example = "B001") + private String batchCode; + + @Schema(description = "质量状态", example = "合格") + private Integer qualityStatus; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java new file mode 100644 index 000000000..7184248e4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 管理后台 - MES 销售退货相关 + * + * @author 芋道源码 + */ +@Schema(description = "管理后台 - MES 销售退货单行新增/修改 Request VO") +@Data +public class MesWmReturnSalesLineSaveReqVO { + + @Schema(description = "行ID", example = "1") + private Long id; + + @Schema(description = "退货单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退货单ID不能为空") + private Long returnId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料ID不能为空") + private Long itemId; + + @Schema(description = "退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "退货数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "退货数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次号", example = "B20250101") + private Long batchId; + + @Schema(description = "是否需要质检", example = "true") + private Boolean rqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorController.java new file mode 100644 index 000000000..35b4cd001 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorController.java @@ -0,0 +1,164 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.returnvendor.vo.MesWmReturnVendorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDO; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.wm.returnvendor.MesWmReturnVendorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 供应商退货单") +@RestController +@RequestMapping("/mes/wm/return-vendor") +@Validated +public class MesWmReturnVendorController { + + @Resource + private MesWmReturnVendorService returnVendorService; + @Resource + private MesMdVendorService vendorService; + + @PostMapping("/create") + @Operation(summary = "创建供应商退货单") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:create')") + public CommonResult createReturnVendor(@Valid @RequestBody MesWmReturnVendorSaveReqVO createReqVO) { + return success(returnVendorService.createReturnVendor(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改供应商退货单") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:update')") + public CommonResult updateReturnVendor(@Valid @RequestBody MesWmReturnVendorSaveReqVO updateReqVO) { + returnVendorService.updateReturnVendor(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除供应商退货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:delete')") + public CommonResult deleteReturnVendor(@RequestParam("id") Long id) { + returnVendorService.deleteReturnVendor(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得供应商退货单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:query')") + public CommonResult getReturnVendor(@RequestParam("id") Long id) { + MesWmReturnVendorDO returnVendor = returnVendorService.getReturnVendor(id); + if (returnVendor == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(returnVendor)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得供应商退货单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:query')") + public CommonResult> getReturnVendorPage( + @Valid MesWmReturnVendorPageReqVO pageReqVO) { + PageResult pageResult = returnVendorService.getReturnVendorPage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出供应商退货单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportReturnVendorExcel(@Valid MesWmReturnVendorPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = returnVendorService.getReturnVendorPage(pageReqVO); + ExcelUtils.write(response, "供应商退货单.xls", "数据", MesWmReturnVendorRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交供应商退货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:update')") + public CommonResult submitReturnVendor(@RequestParam("id") Long id) { + returnVendorService.submitReturnVendor(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "执行拣货") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:update')") + public CommonResult stockReturnVendor(@RequestParam("id") Long id) { + returnVendorService.stockReturnVendor(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成供应商退货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:finish')") + public CommonResult finishReturnVendor(@RequestParam("id") Long id) { + returnVendorService.finishReturnVendor(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消供应商退货单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:update')") + public CommonResult cancelReturnVendor(@RequestParam("id") Long id) { + returnVendorService.cancelReturnVendor(id); + return success(true); + } + + @GetMapping("/check-quantity") + @Operation(summary = "校验供应商退货单数量", description = "校验每行明细数量之和是否等于行退货数量") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:query')") + public CommonResult checkReturnVendorQuantity(@RequestParam("id") Long id) { + return success(returnVendorService.checkReturnVendorQuantity(id)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map vendorMap = vendorService.getVendorMap( + convertSet(list, MesWmReturnVendorDO::getVendorId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnVendorRespVO.class, vo -> + MapUtils.findAndThen(vendorMap, vo.getVendorId(), vendor -> + vo.setVendorCode(vendor.getCode()).setVendorName(vendor.getName()).setVendorNickname(vendor.getNickname()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorDetailController.java new file mode 100644 index 000000000..5da901670 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorDetailController.java @@ -0,0 +1,142 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.detail.MesWmReturnVendorDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.detail.MesWmReturnVendorDetailSaveReqVO; +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.wm.returnvendor.MesWmReturnVendorDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.returnvendor.MesWmReturnVendorDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 供应商退货明细") +@RestController +@RequestMapping("/mes/wm/return-vendor-detail") +@Validated +public class MesWmReturnVendorDetailController { + + @Resource + private MesWmReturnVendorDetailService returnVendorDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建供应商退货明细") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:create')") + public CommonResult createReturnVendorDetail(@Valid @RequestBody MesWmReturnVendorDetailSaveReqVO createReqVO) { + return success(returnVendorDetailService.createReturnVendorDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改供应商退货明细") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:update')") + public CommonResult updateReturnVendorDetail(@Valid @RequestBody MesWmReturnVendorDetailSaveReqVO updateReqVO) { + returnVendorDetailService.updateReturnVendorDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除供应商退货明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:delete')") + public CommonResult deleteReturnVendorDetail(@RequestParam("id") Long id) { + returnVendorDetailService.deleteReturnVendorDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得供应商退货明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:query')") + public CommonResult getReturnVendorDetail(@RequestParam("id") Long id) { + MesWmReturnVendorDetailDO detail = returnVendorDetailService.getReturnVendorDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得供应商退货明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:query')") + public CommonResult> getReturnVendorDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = returnVendorDetailService.getReturnVendorDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmReturnVendorDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmReturnVendorDetailDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmReturnVendorDetailDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmReturnVendorDetailDO::getAreaId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnVendorDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()); + vo.setItemName(item.getName()); + vo.setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorLineController.java new file mode 100644 index 000000000..f993dfda5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/MesWmReturnVendorLineController.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLineSaveReqVO; +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.wm.returnvendor.MesWmReturnVendorLineDO; +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.wm.returnvendor.MesWmReturnVendorLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 供应商退货单行") +@RestController +@RequestMapping("/mes/wm/return-vendor-line") +@Validated +public class MesWmReturnVendorLineController { + + @Resource + private MesWmReturnVendorLineService returnVendorLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建供应商退货单行") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:create')") + public CommonResult createReturnVendorLine(@Valid @RequestBody MesWmReturnVendorLineSaveReqVO createReqVO) { + return success(returnVendorLineService.createReturnVendorLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改供应商退货单行") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:update')") + public CommonResult updateReturnVendorLine(@Valid @RequestBody MesWmReturnVendorLineSaveReqVO updateReqVO) { + returnVendorLineService.updateReturnVendorLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除供应商退货单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:delete')") + public CommonResult deleteReturnVendorLine(@RequestParam("id") Long id) { + returnVendorLineService.deleteReturnVendorLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得供应商退货单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:query')") + public CommonResult getReturnVendorLine(@RequestParam("id") Long id) { + MesWmReturnVendorLineDO line = returnVendorLineService.getReturnVendorLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得供应商退货单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:query')") + public CommonResult> getReturnVendorLinePage( + @Valid MesWmReturnVendorLinePageReqVO pageReqVO) { + PageResult pageResult = returnVendorLineService.getReturnVendorLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/list-by-return-vendor") + @Operation(summary = "获得供应商退货单行列表(按退货单编号)") + @Parameter(name = "returnId", description = "退货单编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-return-vendor:query')") + public CommonResult> getReturnVendorLineListByReturnId( + @RequestParam("returnId") Long returnId) { + List list = returnVendorLineService.getReturnVendorLineListByReturnId(returnId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmReturnVendorLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmReturnVendorLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()); + vo.setItemName(item.getName()); + vo.setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorPageReqVO.java new file mode 100644 index 000000000..d9ed26713 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorPageReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Schema(description = "管理后台 - MES 供应商退货单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmReturnVendorPageReqVO extends PageParam { + + @Schema(description = "退货单编号", example = "RV20250226001") + private String code; + + @Schema(description = "退货单名称", example = "供应商退货") + private String name; + + @Schema(description = "采购订单编号") + private String purchaseOrderCode; + + @Schema(description = "供应商 ID", example = "1") + private Long vendorId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorRespVO.java new file mode 100644 index 000000000..e6f02635d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorRespVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 供应商退货单 Response VO") +@Data +public class MesWmReturnVendorRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RV20250226001") + private String code; + + @Schema(description = "退货单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "供应商退货") + private String name; + + @Schema(description = "采购订单编号", example = "PO20250226001") + private String purchaseOrderCode; + + @Schema(description = "供应商 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long vendorId; + + @Schema(description = "供应商编码", example = "V001") + private String vendorCode; + + @Schema(description = "供应商名称", example = "XX供应商") + private String vendorName; + + @Schema(description = "供应商简称", example = "XX") + private String vendorNickname; + + @Schema(description = "退货日期") + private LocalDateTime returnDate; + + @Schema(description = "退货原因", example = "质量不合格") + private String returnReason; + + @Schema(description = "物流单号", example = "SF1234567890") + private String transportCode; + + @Schema(description = "物流联系电话", example = "13800138000") + private String transportTelephone; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorSaveReqVO.java new file mode 100644 index 000000000..720348aff --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorSaveReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 供应商退货单新增/修改 Request VO") +@Data +public class MesWmReturnVendorSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RV20250226001") + @NotBlank(message = "退货单编号不能为空") + private String code; + + @Schema(description = "退货单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "供应商退货") + @NotBlank(message = "退货单名称不能为空") + private String name; + + @Schema(description = "采购订单编号", example = "PO20250226001") + private String purchaseOrderCode; + + @Schema(description = "供应商 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "供应商 ID 不能为空") + private Long vendorId; + + @Schema(description = "退货日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "退货日期不能为空") + private LocalDateTime returnDate; + + @Schema(description = "退货原因", example = "质量不合格") + private String returnReason; + + @Schema(description = "物流单号", example = "SF1234567890") + private String transportCode; + + @Schema(description = "物流联系电话", example = "13800138000") + private String transportTelephone; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailRespVO.java new file mode 100644 index 000000000..c97f337e4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailRespVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 供应商退货明细 Response VO") +@Data +public class MesWmReturnVendorDetailRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "退货单编号", example = "1") + private Long returnId; + + @Schema(description = "行编号", example = "1") + private Long lineId; + + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + private String itemCode; + + @Schema(description = "物料名称", example = "螺丝") + private String itemName; + + @Schema(description = "规格型号", example = "M8*20") + private String specification; + + @Schema(description = "计量单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "退货数量", example = "300.00") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原材料仓库") + private String warehouseName; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A区") + private String locationName; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A01") + private String areaName; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailSaveReqVO.java new file mode 100644 index 000000000..b4aa8bdf0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailSaveReqVO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 供应商退货明细新增/修改 Request VO") +@Data +public class MesWmReturnVendorDetailSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "退货单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退货单行编号不能为空") + private Long lineId; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退货单编号不能为空") + private Long returnId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") + @NotNull(message = "退货数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "退货数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLinePageReqVO.java new file mode 100644 index 000000000..ff4a7e916 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLinePageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 供应商退货单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmReturnVendorLinePageReqVO extends PageParam { + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退货单编号不能为空") + private Long returnId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineRespVO.java new file mode 100644 index 000000000..2fb1a1193 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineRespVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 供应商退货单行 Response VO") +@Data +public class MesWmReturnVendorLineRespVO { + + @Schema(description = "行ID", example = "1") + private Long id; + + @Schema(description = "退货单ID", example = "1") + private Long returnId; + + @Schema(description = "物料ID", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "退货数量", example = "100.00") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineSaveReqVO.java new file mode 100644 index 000000000..78abd5974 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/line/MesWmReturnVendorLineSaveReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 供应商退货单行 Save Request VO") +@Data +public class MesWmReturnVendorLineSaveReqVO { + + @Schema(description = "行ID", example = "1") + private Long id; + + @Schema(description = "退货单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退货单ID不能为空") + private Long returnId; + + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料ID不能为空") + private Long itemId; + + @Schema(description = "退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "退货数量不能为空") + @DecimalMin(value = "0", inclusive = false, message = "退货数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次ID", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH20260101001") + private String batchCode; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeController.java new file mode 100644 index 000000000..1d9f51b12 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeController.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.salesnotice.vo.MesWmSalesNoticePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticeRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 发货通知单") +@RestController +@RequestMapping("/mes/wm/sales-notice") +@Validated +public class MesWmSalesNoticeController { + + @Resource + private MesWmSalesNoticeService salesNoticeService; + + @Resource + private MesMdClientService clientService; + + @PostMapping("/create") + @Operation(summary = "创建发货通知单") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:create')") + public CommonResult createSalesNotice(@Valid @RequestBody MesWmSalesNoticeSaveReqVO createReqVO) { + return success(salesNoticeService.createSalesNotice(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改发货通知单") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:update')") + public CommonResult updateSalesNotice(@Valid @RequestBody MesWmSalesNoticeSaveReqVO updateReqVO) { + salesNoticeService.updateSalesNotice(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除发货通知单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:delete')") + public CommonResult deleteSalesNotice(@RequestParam("id") Long id) { + salesNoticeService.deleteSalesNotice(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得发货通知单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:query')") + public CommonResult getSalesNotice(@RequestParam("id") Long id) { + MesWmSalesNoticeDO notice = salesNoticeService.getSalesNotice(id); + if (notice == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(notice)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得发货通知单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:query')") + public CommonResult> getSalesNoticePage( + @Valid MesWmSalesNoticePageReqVO pageReqVO) { + PageResult pageResult = salesNoticeService.getSalesNoticePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出发货通知单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportSalesNoticeExcel(@Valid MesWmSalesNoticePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = salesNoticeService.getSalesNoticePage(pageReqVO); + ExcelUtils.write(response, "发货通知单.xls", "数据", MesWmSalesNoticeRespVO.class, + buildRespVOList(pageResult.getList())); + } + + @PutMapping("/submit") + @Operation(summary = "提交发货通知单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:update')") + public CommonResult submitSalesNotice(@RequestParam("id") Long id) { + salesNoticeService.submitSalesNotice(id); + return success(true); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得发货通知单精简列表") + @Parameter(name = "status", description = "状态", example = "1") + public CommonResult> getSalesNoticeSimpleList( + @RequestParam(value = "status", required = false) Integer status) { + List list = salesNoticeService.getSalesNoticeListByStatus(status); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map clientMap = clientService.getClientMap( + convertSet(list, MesWmSalesNoticeDO::getClientId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmSalesNoticeRespVO.class, vo -> { + MapUtils.findAndThen(clientMap, vo.getClientId(), client -> + vo.setClientCode(client.getCode()).setClientName(client.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeLineController.java new file mode 100644 index 000000000..2f349ec03 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeLineController.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line.MesWmSalesNoticeLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line.MesWmSalesNoticeLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line.MesWmSalesNoticeLineSaveReqVO; +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.wm.salesnotice.MesWmSalesNoticeLineDO; +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.wm.salesnotice.MesWmSalesNoticeLineService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 发货通知单行") +@RestController +@RequestMapping("/mes/wm/sales-notice-line") +@Validated +public class MesWmSalesNoticeLineController { + + @Resource + private MesWmSalesNoticeLineService salesNoticeLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @PostMapping("/create") + @Operation(summary = "创建发货通知单行") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:create')") + public CommonResult createSalesNoticeLine(@Valid @RequestBody MesWmSalesNoticeLineSaveReqVO createReqVO) { + return success(salesNoticeLineService.createSalesNoticeLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改发货通知单行") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:update')") + public CommonResult updateSalesNoticeLine(@Valid @RequestBody MesWmSalesNoticeLineSaveReqVO updateReqVO) { + salesNoticeLineService.updateSalesNoticeLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除发货通知单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:delete')") + public CommonResult deleteSalesNoticeLine(@RequestParam("id") Long id) { + salesNoticeLineService.deleteSalesNoticeLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得发货通知单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:query')") + public CommonResult getSalesNoticeLine(@RequestParam("id") Long id) { + MesWmSalesNoticeLineDO line = salesNoticeLineService.getSalesNoticeLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得发货通知单行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-sales-notice:query')") + public CommonResult> getSalesNoticeLinePage( + @Valid MesWmSalesNoticeLinePageReqVO pageReqVO) { + PageResult pageResult = salesNoticeLineService.getSalesNoticeLinePage(pageReqVO); + return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmSalesNoticeLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmSalesNoticeLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticePageReqVO.java new file mode 100644 index 000000000..d7568df34 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticePageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 发货通知单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmSalesNoticePageReqVO extends PageParam { + + @Schema(description = "通知单编码", example = "SN202603010001") + private String noticeCode; + + @Schema(description = "通知单名称", example = "测试发货通知") + private String noticeName; + + @Schema(description = "销售订单编号", example = "SO202603010001") + private String salesOrderCode; + + @Schema(description = "客户编号", example = "1") + private Long clientId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java new file mode 100644 index 000000000..bf453e634 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 发货通知单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmSalesNoticeRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "通知单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "SN202603010001") + @ExcelProperty("通知单编码") + private String noticeCode; + + @Schema(description = "通知单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试发货通知") + @ExcelProperty("通知单名称") + private String noticeName; + + @Schema(description = "销售订单编号", example = "SO202603010001") + @ExcelProperty("销售订单编号") + private String salesOrderCode; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long clientId; + + @Schema(description = "客户编码", example = "C001") + @ExcelProperty("客户编码") + private String clientCode; + + @Schema(description = "客户名称", example = "某客户") + @ExcelProperty("客户名称") + private String clientName; + + @Schema(description = "发货日期", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("发货日期") + private LocalDateTime salesDate; + + @Schema(description = "收货人", example = "张三") + @ExcelProperty("收货人") + private String recipientName; + + @Schema(description = "联系方式", example = "13800138000") + @ExcelProperty("联系方式") + private String recipientTelephone; + + @Schema(description = "收货地址", example = "北京市朝阳区xxx") + @ExcelProperty("收货地址") + private String recipientAddress; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeSaveReqVO.java new file mode 100644 index 000000000..ee7b87b72 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeSaveReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 发货通知单新增/修改 Request VO") +@Data +public class MesWmSalesNoticeSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "通知单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "SN202603010001") + @NotEmpty(message = "通知单编码不能为空") + private String noticeCode; + + @Schema(description = "通知单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试发货通知") + @NotEmpty(message = "通知单名称不能为空") + private String noticeName; + + @Schema(description = "销售订单编号", example = "SO202603010001") + private String salesOrderCode; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "客户编号不能为空") + private Long clientId; + + @Schema(description = "发货日期", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "发货日期不能为空") + private LocalDateTime salesDate; + + @Schema(description = "收货人", example = "张三") + private String recipientName; + + @Schema(description = "联系方式", example = "13800138000") + private String recipientTelephone; + + @Schema(description = "收货地址", example = "北京市朝阳区xxx") + private String recipientAddress; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLinePageReqVO.java new file mode 100644 index 000000000..c3b7180c4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLinePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 发货通知单行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmSalesNoticeLinePageReqVO extends PageParam { + + @Schema(description = "发货通知单编号", example = "1") + private Long noticeId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLineRespVO.java new file mode 100644 index 000000000..be8b280c6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLineRespVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 发货通知单行 Response VO") +@Data +public class MesWmSalesNoticeLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "发货通知单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long noticeId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "M001") + private String itemCode; + + @Schema(description = "物料名称", example = "产品A") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "个") + private String unitMeasureName; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH001") + private String batchCode; + + @Schema(description = "发货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal quantity; + + @Schema(description = "是否检验", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean oqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLineSaveReqVO.java new file mode 100644 index 000000000..d6ba34169 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/line/MesWmSalesNoticeLineSaveReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 发货通知单行新增/修改 Request VO") +@Data +public class MesWmSalesNoticeLineSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "发货通知单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "发货通知单编号不能为空") + private Long noticeId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "批次号", example = "BATCH001") + private String batchCode; + + @Schema(description = "发货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "发货数量不能为空") + @DecimalMin(value = "0.01", message = "发货数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "是否检验", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否检验不能为空") + private Boolean oqcCheckFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/MesWmSnController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/MesWmSnController.java new file mode 100644 index 000000000..e9c19b489 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/MesWmSnController.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.sn; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.sn.vo.MesWmSnGenerateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnGroupRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnRespVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.sn.MesWmSnService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES SN 码") +@RestController +@RequestMapping("/mes/wm/sn") +@Validated +public class MesWmSnController { + + @Resource + private MesWmSnService snService; + @Resource + private MesMdItemService itemService; + + @PostMapping("/generate") + @Operation(summary = "生成 SN 码") + @PreAuthorize("@ss.hasPermission('mes:wm-sn:create')") + public CommonResult generateSnCodes(@Valid @RequestBody MesWmSnGenerateReqVO reqVO) { + snService.generateSnCodes(reqVO); + return success(true); + } + + @GetMapping("/group-page") + @Operation(summary = "获得 SN 码分组分页") + @PreAuthorize("@ss.hasPermission('mes:wm-sn:query')") + public CommonResult> getSnGroupPage(@Valid MesWmSnPageReqVO reqVO) { + PageResult pageResult = snService.getSnGroupPage(reqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + buildGroupItemInfo(pageResult.getList()); + return success(pageResult); + } + + @DeleteMapping("/delete-batch") + @Operation(summary = "批量删除 SN 码(按批次 UUID)") + @Parameter(name = "uuid", description = "批次 UUID", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-sn:delete')") + public CommonResult deleteSnBatch(@RequestParam("uuid") @NotBlank(message = "批次 UUID 不能为空") String uuid) { + snService.deleteSnByUuid(uuid); + return success(true); + } + + @GetMapping("/group-export-excel") + @Operation(summary = "导出 SN 码分组 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-sn:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportSnGroupExcel(@Valid MesWmSnPageReqVO reqVO, HttpServletResponse response) throws IOException { + reqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = snService.getSnGroupPage(reqVO).getList(); + buildGroupItemInfo(list); + ExcelUtils.write(response, "SN码分组.xls", "数据", MesWmSnGroupRespVO.class, list); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出批次 SN 码明细 Excel") + @Parameter(name = "uuid", description = "批次 UUID", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-sn:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportSnExcel(@RequestParam("uuid") String uuid, HttpServletResponse response) throws IOException { + List list = BeanUtils.toBean(snService.getSnListByUuid(uuid), MesWmSnRespVO.class); + buildItemInfo(list); + ExcelUtils.write(response, "SN码明细.xls", "数据", MesWmSnRespVO.class, list); + } + + // ==================== 拼接 VO ==================== + + private void buildGroupItemInfo(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + Map itemMap = itemService.getItemMap(convertSet(list, MesWmSnGroupRespVO::getItemId)); + list.forEach(vo -> MapUtils.findAndThen(itemMap, vo.getItemId(), item -> + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()))); + } + + private void buildItemInfo(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + Map itemMap = itemService.getItemMap(convertSet(list, MesWmSnRespVO::getItemId)); + list.forEach(vo -> MapUtils.findAndThen(itemMap, vo.getItemId(), item -> + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGenerateReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGenerateReqVO.java new file mode 100644 index 000000000..039c56eaf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGenerateReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +@Schema(description = "管理后台 - MES SN 码生成 Request VO") +@Data +public class MesWmSnGenerateReqVO { + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "批次号", example = "BATCH001") + @Size(max = 100, message = "批次号长度不能超过 100 个字符") + private String batchCode; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "生成数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "生成数量不能为空") + @Min(value = 1, message = "生成数量最小为 1") + @Max(value = 1000, message = "生成数量最大为 1000") + private Integer count; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java new file mode 100644 index 000000000..ed2883050 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES SN 码分组 Response VO") +@Data +@Accessors(chain = true) +public class MesWmSnGroupRespVO { + + @Schema(description = "批次 UUID", example = "550e8400-e29b-41d4-a716-446655440000") + private String uuid; + + @Schema(description = "SN 码数量", example = "100") + @ExcelProperty("SN 码数量") + private Integer count; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + @ExcelProperty("物料编码") + private String itemCode; + + @Schema(description = "物料名称", example = "物料A") + @ExcelProperty("物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "100*200") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "批次号", example = "BATCH001") + @ExcelProperty("批次号") + private String batchCode; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "创建时间") + @ExcelProperty("生成时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnPageReqVO.java new file mode 100644 index 000000000..6578e2e25 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES SN 码分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmSnPageReqVO extends PageParam { + + @Schema(description = "批次 UUID", example = "550e8400-e29b-41d4-a716-446655440000") + private String uuid; + + @Schema(description = "SN 码", example = "SN20260305000001") + private String code; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "批次号", example = "BATCH001") + private String batchCode; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java new file mode 100644 index 000000000..f42011180 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES SN 码 Response VO") +@Data +@Accessors(chain = true) +public class MesWmSnRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "批次 UUID", example = "550e8400-e29b-41d4-a716-446655440000") + private String uuid; + + @Schema(description = "SN 码", example = "SN20260305000001") + @ExcelProperty("SN 码") + private String code; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + @ExcelProperty("物料编码") + private String itemCode; + + @Schema(description = "物料名称", example = "物料A") + @ExcelProperty("物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "100*200") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "批次号", example = "BATCH001") + @ExcelProperty("批次号") + private String batchCode; + + @Schema(description = "生产工单编号", example = "1") + private Long workOrderId; + + @Schema(description = "创建时间") + @ExcelProperty("生成时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanController.java new file mode 100644 index 000000000..f010a6b2c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanController.java @@ -0,0 +1,116 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.stocktaking.plan.vo.MesWmStockTakingPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.MesWmStockTakingPlanRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.MesWmStockTakingPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanDO; +import cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan.MesWmStockTakingPlanService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 盘点方案") +@RestController +@RequestMapping("/mes/wm/stocktaking-plan") +@Validated +public class MesWmStockTakingPlanController { + + @Resource + private MesWmStockTakingPlanService stockTakingPlanService; + + @PostMapping("/create") + @Operation(summary = "创建盘点方案") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:create')") + public CommonResult createStockTakingPlan(@Valid @RequestBody MesWmStockTakingPlanSaveReqVO createReqVO) { + return success(stockTakingPlanService.createStockTakingPlan(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改盘点方案") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:update')") + public CommonResult updateStockTakingPlan(@Valid @RequestBody MesWmStockTakingPlanSaveReqVO updateReqVO) { + stockTakingPlanService.updateStockTakingPlan(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新盘点方案状态") + @Parameters({ + @Parameter(name = "id", description = "编号", required = true), + @Parameter(name = "status", description = "状态", required = true) + }) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:update')") + public CommonResult updateStockTakingPlanStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockTakingPlanService.updateStockTakingPlanStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除盘点方案") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:delete')") + public CommonResult deleteStockTakingPlan(@RequestParam("id") Long id) { + stockTakingPlanService.deleteStockTakingPlan(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得盘点方案") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:query')") + public CommonResult getStockTakingPlan(@RequestParam("id") Long id) { + MesWmStockTakingPlanDO plan = stockTakingPlanService.getStockTakingPlan(id); + return success(plan == null ? null : BeanUtils.toBean(plan, MesWmStockTakingPlanRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得盘点方案分页") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:query')") + public CommonResult> getStockTakingPlanPage(@Valid MesWmStockTakingPlanPageReqVO pageReqVO) { + PageResult pageResult = stockTakingPlanService.getStockTakingPlanPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesWmStockTakingPlanRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出盘点方案 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportStockTakingPlanExcel(@Valid MesWmStockTakingPlanPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = stockTakingPlanService.getStockTakingPlanPage(pageReqVO); + ExcelUtils.write(response, "盘点方案.xls", "数据", MesWmStockTakingPlanRespVO.class, + BeanUtils.toBean(pageResult.getList(), MesWmStockTakingPlanRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得已启用的盘点方案精简列表") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") + public CommonResult> getEnabledStockTakingPlanSimpleList() { + List list = stockTakingPlanService.getStockTakingPlanListByStatus( + CommonStatusEnum.ENABLE.getStatus()); + return success(BeanUtils.toBean(list, MesWmStockTakingPlanRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanParamController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanParamController.java new file mode 100644 index 000000000..f3494abb3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanParamController.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param.MesWmStockTakingPlanParamPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param.MesWmStockTakingPlanParamRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param.MesWmStockTakingPlanParamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanParamDO; +import cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan.MesWmStockTakingPlanParamService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 盘点方案参数") +@RestController +@RequestMapping("/mes/wm/stocktaking-plan-param") +@Validated +public class MesWmStockTakingPlanParamController { + + @Resource + private MesWmStockTakingPlanParamService stockTakingPlanParamService; + + @PostMapping("/create") + @Operation(summary = "创建盘点方案参数") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:update')") + public CommonResult createStockTakingPlanParam(@Valid @RequestBody MesWmStockTakingPlanParamSaveReqVO createReqVO) { + return success(stockTakingPlanParamService.createStockTakingPlanParam(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改盘点方案参数") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:update')") + public CommonResult updateStockTakingPlanParam(@Valid @RequestBody MesWmStockTakingPlanParamSaveReqVO updateReqVO) { + stockTakingPlanParamService.updateStockTakingPlanParam(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除盘点方案参数") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:update')") + public CommonResult deleteStockTakingPlanParam(@RequestParam("id") Long id) { + stockTakingPlanParamService.deleteStockTakingPlanParam(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得盘点方案参数") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:query')") + public CommonResult getStockTakingPlanParam(@RequestParam("id") Long id) { + MesWmStockTakingPlanParamDO param = stockTakingPlanParamService.getStockTakingPlanParam(id); + return success(param == null ? null : BeanUtils.toBean(param, MesWmStockTakingPlanParamRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得盘点方案参数分页") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-plan:query')") + public CommonResult> getStockTakingPlanParamPage( + @Valid MesWmStockTakingPlanParamPageReqVO pageReqVO) { + PageResult pageResult = stockTakingPlanParamService.getStockTakingPlanParamPage(pageReqVO); + return success(new PageResult<>(BeanUtils.toBean(pageResult.getList(), MesWmStockTakingPlanParamRespVO.class), pageResult.getTotal())); + } + + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanPageReqVO.java new file mode 100644 index 000000000..e4153a5c2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanPageReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Schema(description = "管理后台 - MES 盘点方案分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmStockTakingPlanPageReqVO extends PageParam { + + @Schema(description = "方案编码", example = "STP202603080001") + private String code; + + @Schema(description = "方案名称", example = "原料仓月度盘点方案") + private String name; + + @Schema(description = "盘点类型", example = "1") + private Integer type; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanRespVO.java new file mode 100644 index 000000000..1c684177a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanRespVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 盘点方案 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmStockTakingPlanRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "方案编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "STP202603080001") + @ExcelProperty("方案编码") + private String code; + + @Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料仓月度盘点方案") + @ExcelProperty("方案名称") + private String name; + + @Schema(description = "盘点类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("盘点类型") + private Integer type; + + @Schema(description = "计划开始时间") + @ExcelProperty("计划开始时间") + private LocalDateTime startTime; + + @Schema(description = "计划结束时间") + @ExcelProperty("计划结束时间") + private LocalDateTime endTime; + + @Schema(description = "是否盲盘", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @ExcelProperty("是否盲盘") + private Boolean blindFlag; + + @Schema(description = "是否冻结库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @ExcelProperty("是否冻结库存") + private Boolean frozen; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanSaveReqVO.java new file mode 100644 index 000000000..5db85f8f7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanSaveReqVO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 盘点方案新增/修改 Request VO") +@Data +public class MesWmStockTakingPlanSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "方案编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "STP202603080001") + @NotEmpty(message = "方案编码不能为空") + private String code; + + @Schema(description = "方案名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料仓月度盘点方案") + @NotEmpty(message = "方案名称不能为空") + private String name; + + @Schema(description = "盘点类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "盘点类型不能为空") + private Integer type; + + @Schema(description = "计划开始时间") + private LocalDateTime startTime; + + @Schema(description = "计划结束时间") + private LocalDateTime endTime; + + @Schema(description = "是否盲盘", example = "false") + @NotNull(message = "是否盲盘不能为空") + private Boolean blindFlag; + + @Schema(description = "是否冻结库存", example = "false") + @NotNull(message = "是否冻结库存不能为空") + private Boolean frozen; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamPageReqVO.java new file mode 100644 index 000000000..2140b60d5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamPageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 盘点方案参数分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmStockTakingPlanParamPageReqVO extends PageParam { + + @Schema(description = "方案 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "方案 ID 不能为空") + private Long planId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamRespVO.java new file mode 100644 index 000000000..332244f71 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamRespVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - MES 盘点方案参数 Response VO") +@Data +public class MesWmStockTakingPlanParamRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "方案 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long planId; + + @Schema(description = "参数类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "102") + private Integer type; + + @Schema(description = "参数值 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long valueId; + + @Schema(description = "参数值编码", example = "WH001") + private String valueCode; + + @Schema(description = "参数值名称", example = "原料仓") + private String valueName; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamSaveReqVO.java new file mode 100644 index 000000000..00c7f6d98 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/param/MesWmStockTakingPlanParamSaveReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 盘点方案参数新增/修改 Request VO") +@Data +public class MesWmStockTakingPlanParamSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "方案 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "方案 ID 不能为空") + private Long planId; + + @Schema(description = "参数类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "102") + @NotNull(message = "参数类型不能为空") + private Integer type; + + @Schema(description = "参数值 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "参数值 ID 不能为空") + private Long valueId; + + @Schema(description = "参数值编码", example = "WH001") + private String valueCode; + + @Schema(description = "参数值名称", example = "原料仓") + private String valueName; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskController.java new file mode 100644 index 000000000..5318aa56e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskController.java @@ -0,0 +1,152 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.stocktaking.task.vo.*; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskDO; +import cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan.MesWmStockTakingPlanService; +import cn.iocoder.yudao.module.mes.service.wm.stocktaking.task.MesWmStockTakingTaskService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +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.convertSet; + +@Tag(name = "管理后台 - MES 盘点任务") +@RestController +@RequestMapping("/mes/wm/stocktaking-task") +@Validated +public class MesWmStockTakingTaskController { + + @Resource + private MesWmStockTakingTaskService stockTakingTaskService; + @Resource + private MesWmStockTakingPlanService stockTakingPlanService; + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建盘点任务") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:create')") + public CommonResult createStockTakingTask(@Valid @RequestBody MesWmStockTakingTaskSaveReqVO createReqVO) { + return success(stockTakingTaskService.createStockTakingTask(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改盘点任务") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + public CommonResult updateStockTakingTask(@Valid @RequestBody MesWmStockTakingTaskSaveReqVO updateReqVO) { + stockTakingTaskService.updateStockTakingTask(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除盘点任务") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:delete')") + public CommonResult deleteStockTakingTask(@RequestParam("id") Long id) { + stockTakingTaskService.deleteStockTakingTask(id); + return success(true); + } + + @PutMapping("/submit") + @Operation(summary = "提交盘点任务") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + public CommonResult submitStockTakingTask(@RequestParam("id") Long id) { + stockTakingTaskService.submitStockTakingTask(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得盘点任务") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") + public CommonResult getStockTakingTask(@RequestParam("id") Long id) { + MesWmStockTakingTaskDO task = stockTakingTaskService.getStockTakingTask(id); + if (task == null) { + return success(null); + } + return success(buildTaskRespVOList(Collections.singletonList(task)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得盘点任务分页") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") + public CommonResult> getStockTakingTaskPage(@Valid MesWmStockTakingTaskPageReqVO pageReqVO) { + PageResult pageResult = stockTakingTaskService.getStockTakingTaskPage(pageReqVO); + return success(new PageResult<>(buildTaskRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出盘点任务 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportStockTakingTaskExcel(@Valid MesWmStockTakingTaskPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = stockTakingTaskService.getStockTakingTaskPage(pageReqVO); + ExcelUtils.write(response, "盘点任务.xls", "数据", MesWmStockTakingTaskRespVO.class, + buildTaskRespVOList(pageResult.getList())); + } + + @PutMapping("/finish") + @Operation(summary = "完成盘点任务") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:finish')") + public CommonResult finishStockTakingTask(@Valid @RequestBody MesWmStockTakingTaskFinishReqVO reqVO) { + stockTakingTaskService.finishStockTakingTask(reqVO.getId()); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消盘点任务") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + public CommonResult cancelStockTakingTask(@RequestParam("id") Long id) { + stockTakingTaskService.cancelStockTakingTask(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + private List buildTaskRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 查询关联数据 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesWmStockTakingTaskDO::getUserId)); + Map planMap = stockTakingPlanService.getStockTakingPlanMap( + convertSet(list, MesWmStockTakingTaskDO::getPlanId)); + // 拼接数据 + return BeanUtils.toBean(list, MesWmStockTakingTaskRespVO.class, vo -> { + MapUtils.findAndThen(userMap, vo.getUserId(), + user -> vo.setUserNickname(user.getNickname())); + MapUtils.findAndThen(planMap, vo.getPlanId(), + plan -> vo.setPlanCode(plan.getCode()).setPlanName(plan.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskLineController.java new file mode 100644 index 000000000..39c8b4b88 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskLineController.java @@ -0,0 +1,144 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line.MesWmStockTakingTaskLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line.MesWmStockTakingTaskLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line.MesWmStockTakingTaskLineSaveReqVO; +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.wm.stocktaking.task.MesWmStockTakingTaskLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.stocktaking.task.MesWmStockTakingTaskLineService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + +@Tag(name = "管理后台 - MES 盘点任务行") +@RestController +@RequestMapping("/mes/wm/stocktaking-task-line") +@Validated +public class MesWmStockTakingTaskLineController { + + @Resource + private MesWmStockTakingTaskLineService stockTakingTaskLineService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + + @GetMapping("/get") + @Operation(summary = "获得盘点任务行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") + public CommonResult getStockTakingTaskLine(@RequestParam("id") Long id) { + MesWmStockTakingTaskLineDO line = stockTakingTaskLineService.getStockTakingTaskLine(id); + if (line == null) { + return success(null); + } + return success(buildStockTakingTaskLineRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得盘点任务行分页") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") + public CommonResult> getStockTakingTaskLinePage( + @Valid MesWmStockTakingTaskLinePageReqVO pageReqVO) { + PageResult pageResult = stockTakingTaskLineService.getStockTakingTaskLinePage(pageReqVO); + return success(new PageResult<>(buildStockTakingTaskLineRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @PostMapping("/create") + @Operation(summary = "创建盘点任务行") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + public CommonResult createStockTakingTaskLine(@Valid @RequestBody MesWmStockTakingTaskLineSaveReqVO createReqVO) { + return success(stockTakingTaskLineService.createStockTakingTaskLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新盘点任务行") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + public CommonResult updateStockTakingTaskLine(@Valid @RequestBody MesWmStockTakingTaskLineSaveReqVO updateReqVO) { + stockTakingTaskLineService.updateStockTakingTaskLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除盘点任务行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + public CommonResult deleteStockTakingTaskLine(@RequestParam("id") Long id) { + stockTakingTaskLineService.deleteStockTakingTaskLine(id); + return success(true); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得盘点任务行精简列表", description = "根据任务编号查询,主要用于前端的下拉选项") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") + public CommonResult> getStockTakingTaskLineSimpleList( + @RequestParam("taskId") Long taskId) { + List list = stockTakingTaskLineService.getStockTakingTaskLineListByTaskId(taskId); + return success(buildStockTakingTaskLineRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildStockTakingTaskLineRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 查询关联数据 + Map itemMap = itemService.getItemMap(convertSet(list, MesWmStockTakingTaskLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmStockTakingTaskLineDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmStockTakingTaskLineDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmStockTakingTaskLineDO::getAreaId)); + // 拼接 VO + return BeanUtils.toBean(list, MesWmStockTakingTaskLineRespVO.class, vo -> { + findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + findAndThen(locationMap, + vo.getLocationId(), location -> vo.setLocationName(location.getName())); + findAndThen(areaMap, + vo.getAreaId(), area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskResultController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskResultController.java new file mode 100644 index 000000000..8ff23aebb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/MesWmStockTakingTaskResultController.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultSaveReqVO; +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.wm.stocktaking.task.MesWmStockTakingTaskResultDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.stocktaking.task.MesWmStockTakingTaskResultService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 盘点结果") +@RestController +@RequestMapping("/mes/wm/stocktaking-task-result") +@Validated +public class MesWmStockTakingTaskResultController { + + @Resource + private MesWmStockTakingTaskResultService stockTakingTaskResultService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + + @GetMapping("/get") + @Operation(summary = "获得盘点结果") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") + public CommonResult getStockTakingTaskResult(@RequestParam("id") Long id) { + MesWmStockTakingTaskResultDO result = stockTakingTaskResultService.getStockTakingTaskResult(id); + if (result == null) { + return success(null); + } + return success(buildStockTakingTaskResultRespVOList(Collections.singletonList(result)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得盘点结果分页") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") + public CommonResult> getStockTakingTaskResultPage( + @Valid MesWmStockTakingTaskResultPageReqVO pageReqVO) { + PageResult pageResult = stockTakingTaskResultService.getStockTakingTaskResultPage(pageReqVO); + return success(new PageResult<>(buildStockTakingTaskResultRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @PostMapping("/create") + @Operation(summary = "创建盘点结果") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + @Transactional(rollbackFor = Exception.class) + public CommonResult createStockTakingTaskResult(@Valid @RequestBody MesWmStockTakingTaskResultSaveReqVO createReqVO) { + return success(stockTakingTaskResultService.createStockTakingTaskResult(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新盘点结果") + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + @Transactional(rollbackFor = Exception.class) + public CommonResult updateStockTakingTaskResult(@Valid @RequestBody MesWmStockTakingTaskResultSaveReqVO updateReqVO) { + stockTakingTaskResultService.updateStockTakingTaskResult(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除盘点结果") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:update')") + @Transactional(rollbackFor = Exception.class) + public CommonResult deleteStockTakingTaskResult(@RequestParam("id") Long id) { + stockTakingTaskResultService.deleteStockTakingTaskResult(id); + return success(true); + } + + // ==================== 拼接 VO ==================== + + + private List buildStockTakingTaskResultRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 查询关联数据 + Map itemMap = itemService.getItemMap( + convertSet(list, MesWmStockTakingTaskResultDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmStockTakingTaskResultDO::getWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmStockTakingTaskResultDO::getLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmStockTakingTaskResultDO::getAreaId)); + // 拼接 VO + return BeanUtils.toBean(list, MesWmStockTakingTaskResultRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unit -> vo.setUnitMeasureName(unit.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), + warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getLocationId(), + location -> vo.setLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getAreaId(), + area -> vo.setAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskCancelReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskCancelReqVO.java new file mode 100644 index 000000000..639d351a5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskCancelReqVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 盘点任务取消 Request VO") +@Data +public class MesWmStockTakingTaskCancelReqVO { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "任务编号不能为空") + private Long id; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskFinishReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskFinishReqVO.java new file mode 100644 index 000000000..210aae724 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskFinishReqVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 盘点任务完成 Request VO") +@Data +public class MesWmStockTakingTaskFinishReqVO { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "任务编号不能为空") + private Long id; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskPageReqVO.java new file mode 100644 index 000000000..ac2c3a0c6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskPageReqVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 盘点任务分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmStockTakingTaskPageReqVO extends PageParam { + + @Schema(description = "任务编码", example = "ST202603080001") + private String code; + + @Schema(description = "任务名称", example = "原料仓月度盘点任务") + private String name; + + @Schema(description = "盘点类型", example = "1") + private Integer type; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "盘点人 ID", example = "1") + private Long userId; + + @Schema(description = "来源方案 ID", example = "1") + private Long planId; + + @Schema(description = "盘点日期范围") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] takingDate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskRespVO.java new file mode 100644 index 000000000..4e3115b62 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskRespVO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 盘点任务 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmStockTakingTaskRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "任务编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ST202603080001") + @ExcelProperty("任务编码") + private String code; + + @Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料仓月度盘点任务") + @ExcelProperty("任务名称") + private String name; + + @Schema(description = "盘点日期") + @ExcelProperty("盘点日期") + private LocalDateTime takingDate; + + @Schema(description = "盘点类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("盘点类型") + private Integer type; + + @Schema(description = "盘点人 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long userId; + + @Schema(description = "盘点人昵称", example = "管理员") + @ExcelProperty("盘点人") + private String userNickname; + + @Schema(description = "来源方案 ID", example = "1") + private Long planId; + + @Schema(description = "来源方案编码", example = "STP202603080001") + @ExcelProperty("方案编码") + private String planCode; + + @Schema(description = "来源方案名称", example = "原料仓月度盘点方案") + @ExcelProperty("方案名称") + private String planName; + + @Schema(description = "是否盲盘", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @ExcelProperty("是否盲盘") + private Boolean blindFlag; + + @Schema(description = "是否冻结库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @ExcelProperty("是否冻结库存") + private Boolean frozen; + + @Schema(description = "开始时间") + @ExcelProperty("开始时间") + private LocalDateTime startTime; + + @Schema(description = "结束时间") + @ExcelProperty("结束时间") + private LocalDateTime endTime; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskSaveReqVO.java new file mode 100644 index 000000000..b0608dcfa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskSaveReqVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 盘点任务新增/修改 Request VO") +@Data +public class MesWmStockTakingTaskSaveReqVO { + + @Schema(description = "编号", example = "1024") + private Long id; + + @Schema(description = "任务编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ST202603080001") + @NotEmpty(message = "任务编码不能为空") + private String code; + + @Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料仓月度盘点任务") + @NotEmpty(message = "任务名称不能为空") + private String name; + + @Schema(description = "盘点日期") + private LocalDateTime takingDate; + + @Schema(description = "盘点类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "盘点类型不能为空") + private Integer type; + + @Schema(description = "盘点人 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "盘点人不能为空") + private Long userId; + + @Schema(description = "来源方案 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "来源方案不能为空") + private Long planId; + + @Schema(description = "开始时间") + private LocalDateTime startTime; + + @Schema(description = "结束时间") + private LocalDateTime endTime; + + @Schema(description = "是否盲盘", example = "false") + @NotNull(message = "是否盲盘不能为空") + private Boolean blindFlag; + + @Schema(description = "是否冻结库存", example = "false") + @NotNull(message = "是否冻结库存不能为空") + private Boolean frozen; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskStartReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskStartReqVO.java new file mode 100644 index 000000000..7f8fcd0d7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskStartReqVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 盘点任务开始 Request VO") +@Data +public class MesWmStockTakingTaskStartReqVO { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "任务编号不能为空") + private Long id; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineBatchUpdateReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineBatchUpdateReqVO.java new file mode 100644 index 000000000..114e441e3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineBatchUpdateReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +@Schema(description = "管理后台 - MES 盘点任务行批量更新 Request VO") +@Data +public class MesWmStockTakingTaskLineBatchUpdateReqVO { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "任务编号不能为空") + private Long taskId; + + @Schema(description = "任务行列表") + @NotEmpty(message = "任务行不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "任务行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "任务行编号不能为空") + private Long id; + + @Schema(description = "实盘数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "98.000000") + @NotNull(message = "实盘数量不能为空") + private BigDecimal takingQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLinePageReqVO.java new file mode 100644 index 000000000..50f3da0ea --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLinePageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 盘点任务行分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmStockTakingTaskLinePageReqVO extends PageParam { + + @Schema(description = "盘点任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long taskId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineRespVO.java new file mode 100644 index 000000000..f9377a52f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineRespVO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 盘点任务行 Response VO") +@Data +public class MesWmStockTakingTaskLineRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "任务 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long taskId; + + @Schema(description = "库存台账 ID", example = "1") + private Long materialStockId; + + @Schema(description = "物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + private String unitMeasureName; + + @Schema(description = "批次 ID", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "B202603080001") + private String batchCode; + + @Schema(description = "账面数量", example = "100.000000") + private BigDecimal quantity; + + @Schema(description = "实盘数量", example = "98.000000") + private BigDecimal takingQuantity; + + @Schema(description = "差异数量", example = "-2.000000") + private BigDecimal differenceQuantity; + + @Schema(description = "仓库 ID", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原料仓") + private String warehouseName; + + @Schema(description = "库区 ID", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A 区") + private String locationName; + + @Schema(description = "库位 ID", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A-01") + private String areaName; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineSaveReqVO.java new file mode 100644 index 000000000..eb45c3e1e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/line/MesWmStockTakingTaskLineSaveReqVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - 盘点任务行新增/修改 Request VO") +@Data +public class MesWmStockTakingTaskLineSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "盘点任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "盘点任务编号不能为空") + private Long taskId; + + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "账面数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "账面数量不能为空") + private BigDecimal quantity; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultPageReqVO.java new file mode 100644 index 000000000..5469400ff --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultPageReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Schema(description = "管理后台 - MES 盘点结果分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +public class MesWmStockTakingTaskResultPageReqVO extends PageParam { + + @Schema(description = "任务编号", example = "1") + private Long taskId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "库位编号", example = "1") + private Long areaId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultRespVO.java new file mode 100644 index 000000000..8f074d850 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultRespVO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 盘点结果 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmStockTakingTaskResultRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "任务 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long taskId; + + @Schema(description = "任务行 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long lineId; + + @Schema(description = "库存台账 ID", example = "1") + private Long materialStockId; + + @Schema(description = "物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemId; + + @Schema(description = "物料编码", example = "ITEM001") + @ExcelProperty("物料编码") + private String itemCode; + + @Schema(description = "物料名称", example = "钢板") + @ExcelProperty("物料名称") + private String itemName; + + @Schema(description = "规格型号", example = "10mm*100mm") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "计量单位名称", example = "千克") + @ExcelProperty("计量单位") + private String unitMeasureName; + + @Schema(description = "批次 ID", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "B202603080001") + @ExcelProperty("批次编码") + private String batchCode; + + @Schema(description = "仓库 ID", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原料仓") + @ExcelProperty("仓库") + private String warehouseName; + + @Schema(description = "库区 ID", example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "A 区") + @ExcelProperty("库区") + private String locationName; + + @Schema(description = "库位 ID", example = "1") + private Long areaId; + + @Schema(description = "库位名称", example = "A-01") + @ExcelProperty("库位") + private String areaName; + + @Schema(description = "账面数量", example = "100.000000") + @ExcelProperty("账面数量") + private BigDecimal quantity; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultSaveReqVO.java new file mode 100644 index 000000000..983588353 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultSaveReqVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 盘点结果新增/修改 Request VO") +@Data +public class MesWmStockTakingTaskResultSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "任务 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "任务 ID 不能为空") + private Long taskId; + + @Schema(description = "任务行 ID", example = "1") + private Long lineId; + + @Schema(description = "库存台账 ID", example = "1") + private Long materialStockId; + + @Schema(description = "物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料 ID 不能为空") + private Long itemId; + + @Schema(description = "批次 ID", example = "1") + private Long batchId; + + @Schema(description = "批次编码", example = "B202603080001") + private String batchCode; + + @Schema(description = "仓库 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库 ID 不能为空") + private Long warehouseId; + + @Schema(description = "库区 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库区 ID 不能为空") + private Long locationId; + + @Schema(description = "库位 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库位 ID 不能为空") + private Long areaId; + + @Schema(description = "盘点数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.000000") + @NotNull(message = "盘点数量不能为空") + private BigDecimal takingQuantity; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferController.java new file mode 100644 index 000000000..d4570011e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferController.java @@ -0,0 +1,137 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.wm.transfer.vo.MesWmTransferPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.MesWmTransferRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.MesWmTransferSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDO; +import cn.iocoder.yudao.module.mes.service.wm.transfer.MesWmTransferService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 转移单") +@RestController +@RequestMapping("/mes/wm/transfer") +@Validated +public class MesWmTransferController { + + @Resource + private MesWmTransferService transferService; + + @PostMapping("/create") + @Operation(summary = "创建转移单") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:create')") + public CommonResult createTransfer(@Valid @RequestBody MesWmTransferSaveReqVO createReqVO) { + return success(transferService.createTransfer(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改转移单") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:update')") + public CommonResult updateTransfer(@Valid @RequestBody MesWmTransferSaveReqVO updateReqVO) { + transferService.updateTransfer(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除转移单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:delete')") + public CommonResult deleteTransfer(@RequestParam("id") Long id) { + transferService.deleteTransfer(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得转移单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:query')") + public CommonResult getTransfer(@RequestParam("id") Long id) { + MesWmTransferDO transfer = transferService.getTransfer(id); + return success(BeanUtils.toBean(transfer, MesWmTransferRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得转移单分页") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:query')") + public CommonResult> getTransferPage( + @Valid MesWmTransferPageReqVO pageReqVO) { + PageResult pageResult = transferService.getTransferPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesWmTransferRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出转移单 Excel") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTransferExcel(@Valid MesWmTransferPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = transferService.getTransferPage(pageReqVO); + ExcelUtils.write(response, "转移单.xls", "数据", MesWmTransferRespVO.class, + BeanUtils.toBean(pageResult.getList(), MesWmTransferRespVO.class)); + } + + @PutMapping("/submit") + @Operation(summary = "提交转移单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:update')") + public CommonResult submitTransfer(@RequestParam("id") Long id) { + transferService.submitTransfer(id); + return success(true); + } + + @PutMapping("/confirm") + @Operation(summary = "确认转移单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:update')") + public CommonResult confirmTransfer(@RequestParam("id") Long id) { + transferService.confirmTransfer(id); + return success(true); + } + + @PutMapping("/stock") + @Operation(summary = "执行上架") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:update')") + public CommonResult stockTransfer(@RequestParam("id") Long id) { + transferService.stockTransfer(id); + return success(true); + } + + @PutMapping("/finish") + @Operation(summary = "完成转移单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:finish')") + public CommonResult finishTransfer(@RequestParam("id") Long id) { + transferService.finishTransfer(id); + return success(true); + } + + @PutMapping("/cancel") + @Operation(summary = "取消转移单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:update')") + public CommonResult cancelTransfer(@RequestParam("id") Long id) { + transferService.cancelTransfer(id); + return success(true); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferDetailController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferDetailController.java new file mode 100644 index 000000000..e0ef38188 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferDetailController.java @@ -0,0 +1,139 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.detail.MesWmTransferDetailRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.detail.MesWmTransferDetailSaveReqVO; +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.wm.transfer.MesWmTransferDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.transfer.MesWmTransferDetailService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 调拨明细") +@RestController +@RequestMapping("/mes/wm/transfer-detail") +@Validated +public class MesWmTransferDetailController { + + @Resource + private MesWmTransferDetailService transferDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建调拨明细") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:create')") + public CommonResult createTransferDetail(@Valid @RequestBody MesWmTransferDetailSaveReqVO createReqVO) { + return success(transferDetailService.createTransferDetail(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改调拨明细") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:update')") + public CommonResult updateTransferDetail(@Valid @RequestBody MesWmTransferDetailSaveReqVO updateReqVO) { + transferDetailService.updateTransferDetail(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除调拨明细") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:delete')") + public CommonResult deleteTransferDetail(@RequestParam("id") Long id) { + transferDetailService.deleteTransferDetail(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得调拨明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:query')") + public CommonResult getTransferDetail(@RequestParam("id") Long id) { + MesWmTransferDetailDO detail = transferDetailService.getTransferDetail(id); + if (detail == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(detail)).get(0)); + } + + @GetMapping("/list-by-line") + @Operation(summary = "获得调拨明细列表(按行编号)") + @Parameter(name = "lineId", description = "行编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:query')") + public CommonResult> getTransferDetailListByLineId( + @RequestParam("lineId") Long lineId) { + List list = transferDetailService.getTransferDetailListByLineId(lineId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 查询相关数据 + Map itemMap = itemService.getItemMap(convertSet(list, MesWmTransferDetailDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmTransferDetailDO::getToWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmTransferDetailDO::getToLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmTransferDetailDO::getToAreaId)); + // 拼接数据 + return BeanUtils.toBean(list, MesWmTransferDetailRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getToWarehouseId(), + warehouse -> vo.setToWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getToLocationId(), + location -> vo.setToLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getToAreaId(), + area -> vo.setToAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferLineController.java new file mode 100644 index 000000000..46419b672 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/MesWmTransferLineController.java @@ -0,0 +1,138 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.line.MesWmTransferLineRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.line.MesWmTransferLineSaveReqVO; +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.wm.transfer.MesWmTransferLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +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.wm.transfer.MesWmTransferLineService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 转移单行") +@RestController +@RequestMapping("/mes/wm/transfer-line") +@Validated +public class MesWmTransferLineController { + + @Resource + private MesWmTransferLineService transferLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesMdUnitMeasureService unitMeasureService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建转移单行") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:create')") + public CommonResult createTransferLine(@Valid @RequestBody MesWmTransferLineSaveReqVO createReqVO) { + return success(transferLineService.createTransferLine(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "修改转移单行") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:update')") + public CommonResult updateTransferLine(@Valid @RequestBody MesWmTransferLineSaveReqVO updateReqVO) { + transferLineService.updateTransferLine(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除转移单行") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:delete')") + public CommonResult deleteTransferLine(@RequestParam("id") Long id) { + transferLineService.deleteTransferLine(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得转移单行") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:query')") + public CommonResult getTransferLine(@RequestParam("id") Long id) { + MesWmTransferLineDO line = transferLineService.getTransferLine(id); + if (line == null) { + return success(null); + } + return success(buildRespVOList(Collections.singletonList(line)).get(0)); + } + + @GetMapping("/list") + @Operation(summary = "获得转移单行列表") + @Parameter(name = "transferId", description = "转移单编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-transfer:query')") + public CommonResult> getTransferLineList(@RequestParam("transferId") Long transferId) { + List list = transferLineService.getTransferLineListByTransferId(transferId); + return success(buildRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + private List buildRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 查询相关数据 + Map itemMap = itemService.getItemMap(convertSet(list, MesWmTransferLineDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(list, MesWmTransferLineDO::getFromWarehouseId)); + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmTransferLineDO::getFromLocationId)); + Map areaMap = areaService.getWarehouseAreaMap( + convertSet(list, MesWmTransferLineDO::getFromAreaId)); + // 拼接数据 + return BeanUtils.toBean(list, MesWmTransferLineRespVO.class, vo -> { + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + }); + MapUtils.findAndThen(warehouseMap, vo.getFromWarehouseId(), + warehouse -> vo.setFromWarehouseName(warehouse.getName())); + MapUtils.findAndThen(locationMap, vo.getFromLocationId(), + location -> vo.setFromLocationName(location.getName())); + MapUtils.findAndThen(areaMap, vo.getFromAreaId(), + area -> vo.setFromAreaName(area.getName())); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferPageReqVO.java new file mode 100644 index 000000000..b16dad6c5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 转移单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmTransferPageReqVO extends PageParam { + + @Schema(description = "转移单编号", example = "TR2026020001") + private String code; + + @Schema(description = "转移单名称", example = "钢板转移单") + private String name; + + @Schema(description = "转移单类型", example = "1") + private Integer type; + + @Schema(description = "单据状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferRespVO.java new file mode 100644 index 000000000..e9ce237b1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferRespVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 转移单 Response VO") +@Data +public class MesWmTransferRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "转移单编号", example = "TR2026020001") + private String code; + + @Schema(description = "转移单名称", example = "钢板转移单") + private String name; + + @Schema(description = "转移单类型", example = "1") + private Integer type; + + @Schema(description = "是否配送", example = "true") + private Boolean deliveryFlag; + + @Schema(description = "收货人", example = "张三") + private String recipientName; + + @Schema(description = "联系方式", example = "13800138000") + private String recipientTelephone; + + @Schema(description = "目的地", example = "上海市浦东新区") + private String destinationAddress; + + @Schema(description = "承运商", example = "顺丰速运") + private String carrier; + + @Schema(description = "运输单号", example = "SF123456789") + private String shippingNumber; + + @Schema(description = "是否已确认", example = "false") + private Boolean confirmFlag; + + @Schema(description = "转移日期") + private LocalDateTime transferDate; + + @Schema(description = "单据状态", example = "0") + private Integer status; + + @Schema(description = "备注", example = "备注信息") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferSaveReqVO.java new file mode 100644 index 000000000..cf44709ec --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferSaveReqVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; + +@Schema(description = "管理后台 - MES 转移单 Save Request VO") +@Data +public class MesWmTransferSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "转移单编号", requiredMode = REQUIRED, example = "TR2026020001") + @NotBlank(message = "转移单编号不能为空") + private String code; + + @Schema(description = "转移单名称", requiredMode = REQUIRED, example = "钢板转移单") + @NotBlank(message = "转移单名称不能为空") + private String name; + + @Schema(description = "转移单类型", requiredMode = REQUIRED, example = "1") + @NotNull(message = "转移单类型不能为空") + private Integer type; + + @Schema(description = "是否配送", requiredMode = REQUIRED, example = "true") + @NotNull(message = "是否配送不能为空") + private Boolean deliveryFlag; + + @Schema(description = "收货人", example = "张三") + private String recipientName; + + @Schema(description = "联系方式", example = "13800138000") + private String recipientTelephone; + + @Schema(description = "目的地", example = "上海市浦东新区") + private String destinationAddress; + + @Schema(description = "承运商", example = "顺丰速运") + private String carrier; + + @Schema(description = "运输单号", example = "SF123456789") + private String shippingNumber; + + @Schema(description = "转移日期", requiredMode = REQUIRED) + @NotNull(message = "转移日期不能为空") + private LocalDateTime transferDate; + + @Schema(description = "备注", example = "备注信息") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/detail/MesWmTransferDetailRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/detail/MesWmTransferDetailRespVO.java new file mode 100644 index 000000000..75521dd2d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/detail/MesWmTransferDetailRespVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 调拨明细 Response VO") +@Data +public class MesWmTransferDetailRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "转移单行编号", example = "1") + private Long lineId; + + @Schema(description = "转移单编号", example = "1") + private Long transferId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + @Schema(description = "物料编码") + private String itemCode; + @Schema(description = "物料名称") + private String itemName; + @Schema(description = "规格型号") + private String specification; + @Schema(description = "单位名称") + private String unitMeasureName; + + @Schema(description = "上架数量", example = "100") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + @Schema(description = "批次号") + private String batchCode; + + @Schema(description = "移入仓库编号", example = "1") + private Long toWarehouseId; + @Schema(description = "移入仓库名称") + private String toWarehouseName; + + @Schema(description = "移入库区编号", example = "1") + private Long toLocationId; + @Schema(description = "移入库区名称") + private String toLocationName; + + @Schema(description = "移入库位编号", example = "1") + private Long toAreaId; + @Schema(description = "移入库位名称") + private String toAreaName; + + @Schema(description = "备注", example = "备注信息") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/detail/MesWmTransferDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/detail/MesWmTransferDetailSaveReqVO.java new file mode 100644 index 000000000..7e93f25e2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/detail/MesWmTransferDetailSaveReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.detail; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 调拨明细 Save Request VO") +@Data +public class MesWmTransferDetailSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "转移单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "转移单行编号不能为空") + private Long lineId; + + @Schema(description = "转移单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "转移单编号不能为空") + private Long transferId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "上架数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "上架数量不能为空") + @DecimalMin(value = "0.01", message = "上架数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "移入仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "移入仓库编号不能为空") + private Long toWarehouseId; + + @Schema(description = "移入库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "移入库区编号不能为空") + private Long toLocationId; + + @Schema(description = "移入库位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "移入库位编号不能为空") + private Long toAreaId; + + @Schema(description = "备注", example = "备注信息") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineRespVO.java new file mode 100644 index 000000000..fbf4f96c6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineRespVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 转移单行 Response VO") +@Data +public class MesWmTransferLineRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "转移单编号", example = "1") + private Long transferId; + + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "物料编号", example = "1") + private Long itemId; + @Schema(description = "物料编码") + private String itemCode; + @Schema(description = "物料名称") + private String itemName; + @Schema(description = "规格型号") + private String specification; + @Schema(description = "单位名称") + private String unitMeasureName; + + @Schema(description = "转移数量", example = "100") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + @Schema(description = "批次号") + private String batchCode; + + @Schema(description = "移出仓库编号", example = "1") + private Long fromWarehouseId; + @Schema(description = "移出仓库名称") + private String fromWarehouseName; + + @Schema(description = "移出库区编号", example = "1") + private Long fromLocationId; + @Schema(description = "移出库区名称") + private String fromLocationName; + + @Schema(description = "移出库位编号", example = "1") + private Long fromAreaId; + @Schema(description = "移出库位名称") + private String fromAreaName; + + @Schema(description = "备注", example = "备注信息") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineSaveReqVO.java new file mode 100644 index 000000000..96f776305 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineSaveReqVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.line; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 转移单行 Save Request VO") +@Data +public class MesWmTransferLineSaveReqVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "转移单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "转移单编号不能为空") + private Long transferId; + + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料编号不能为空") + private Long itemId; + + @Schema(description = "转移数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + @NotNull(message = "转移数量不能为空") + @DecimalMin(value = "0.01", message = "转移数量必须大于 0") + private BigDecimal quantity; + + @Schema(description = "批次编号", example = "1") + private Long batchId; + + @Schema(description = "移出仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "移出仓库编号不能为空") + private Long fromWarehouseId; + + @Schema(description = "移出库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "移出库区编号不能为空") + private Long fromLocationId; + + @Schema(description = "移出库位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "移出库位编号不能为空") + private Long fromAreaId; + + @Schema(description = "备注", example = "备注信息") + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseAreaController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseAreaController.java new file mode 100644 index 000000000..b63cd9187 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseAreaController.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area.MesWmWarehouseAreaPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area.MesWmWarehouseAreaRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area.MesWmWarehouseAreaSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 库位") +@RestController +@RequestMapping("/mes/wm/warehouse-area") +@Validated +public class MesWmWarehouseAreaController { + + @Resource + private MesWmWarehouseAreaService areaService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseService warehouseService; + + @PostMapping("/create") + @Operation(summary = "创建库位") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:create')") + public CommonResult createWarehouseArea(@Valid @RequestBody MesWmWarehouseAreaSaveReqVO createReqVO) { + return success(areaService.createWarehouseArea(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新库位") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:update')") + public CommonResult updateWarehouseArea(@Valid @RequestBody MesWmWarehouseAreaSaveReqVO updateReqVO) { + areaService.updateWarehouseArea(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除库位") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:delete')") + public CommonResult deleteWarehouseArea(@RequestParam("id") Long id) { + areaService.deleteWarehouseArea(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得库位") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:query')") + public CommonResult getWarehouseArea(@RequestParam("id") Long id) { + MesWmWarehouseAreaDO area = areaService.getWarehouseArea(id); + if (area == null) { + return success(null); + } + return success(buildWarehouseAreaRespVOList(Collections.singletonList(area)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得库位分页") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:query')") + public CommonResult> getWarehouseAreaPage(@Valid MesWmWarehouseAreaPageReqVO pageReqVO) { + PageResult pageResult = areaService.getWarehouseAreaPage(pageReqVO); + return success(new PageResult<>(buildWarehouseAreaRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得库位精简列表", description = "可按库区过滤") + public CommonResult> getWarehouseAreaSimpleList( + @Parameter(name = "locationId", description = "库区编号") @RequestParam(value = "locationId", required = false) Long locationId) { + List list = areaService.getWarehouseAreaList(locationId); + return success(buildWarehouseAreaRespVOList(list)); + } + + // ==================== 拼接 VO ==================== + + /** + * 批量构建库位响应 VO 列表(填充库区、仓库信息) + * + * @param list 库位列表 + * @return 响应 VO 列表 + */ + private List buildWarehouseAreaRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得库区信息 + Map locationMap = locationService.getWarehouseLocationMap( + convertSet(list, MesWmWarehouseAreaDO::getLocationId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(locationMap.values(), MesWmWarehouseLocationDO::getWarehouseId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmWarehouseAreaRespVO.class, vo -> { + MapUtils.findAndThen(locationMap, vo.getLocationId(), location -> { + vo.setLocationName(location.getName()); + vo.setWarehouseId(location.getWarehouseId()); + MapUtils.findAndThen(warehouseMap, location.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName())); + }); + }); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseController.java new file mode 100644 index 000000000..0667a172d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseController.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehousePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehouseRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehouseSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 仓库") +@RestController +@RequestMapping("/mes/wm/warehouse") +@Validated +public class MesWmWarehouseController { + + @Resource + private MesWmWarehouseService warehouseService; + + @PostMapping("/create") + @Operation(summary = "创建仓库") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:create')") + public CommonResult createWarehouse(@Valid @RequestBody MesWmWarehouseSaveReqVO createReqVO) { + return success(warehouseService.createWarehouse(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新仓库") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:update')") + public CommonResult updateWarehouse(@Valid @RequestBody MesWmWarehouseSaveReqVO updateReqVO) { + warehouseService.updateWarehouse(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除仓库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:delete')") + public CommonResult deleteWarehouse(@RequestParam("id") Long id) { + warehouseService.deleteWarehouse(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得仓库") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:query')") + public CommonResult getWarehouse(@RequestParam("id") Long id) { + MesWmWarehouseDO warehouse = warehouseService.getWarehouse(id); + return success(BeanUtils.toBean(warehouse, MesWmWarehouseRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得仓库分页") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:query')") + public CommonResult> getWarehousePage(@Valid MesWmWarehousePageReqVO pageReqVO) { + PageResult pageResult = warehouseService.getWarehousePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesWmWarehouseRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得仓库精简列表", description = "主要用于前端下拉") + public CommonResult> getWarehouseSimpleList() { + List list = warehouseService.getWarehouseList(); + return success(BeanUtils.toBean(list, MesWmWarehouseRespVO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseLocationController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseLocationController.java new file mode 100644 index 000000000..2668cbf19 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/MesWmWarehouseLocationController.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +@Tag(name = "管理后台 - MES 库区") +@RestController +@RequestMapping("/mes/wm/warehouse-location") +@Validated +public class MesWmWarehouseLocationController { + + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseAreaService areaService; + + @PostMapping("/create") + @Operation(summary = "创建库区") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:create')") + public CommonResult createWarehouseLocation(@Valid @RequestBody MesWmWarehouseLocationSaveReqVO createReqVO) { + return success(locationService.createWarehouseLocation(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新库区") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:update')") + public CommonResult updateWarehouseLocation(@Valid @RequestBody MesWmWarehouseLocationSaveReqVO updateReqVO) { + locationService.updateWarehouseLocation(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除库区") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:delete')") + public CommonResult deleteWarehouseLocation(@RequestParam("id") Long id) { + locationService.deleteWarehouseLocation(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得库区") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:query')") + public CommonResult getWarehouseLocation(@RequestParam("id") Long id) { + MesWmWarehouseLocationDO location = locationService.getWarehouseLocation(id); + if (location == null) { + return success(null); + } + return success(buildWarehouseLocationRespVOList(Collections.singletonList(location)).get(0)); + } + + @GetMapping("/page") + @Operation(summary = "获得库区分页") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:query')") + public CommonResult> getWarehouseLocationPage(@Valid MesWmWarehouseLocationPageReqVO pageReqVO) { + PageResult pageResult = locationService.getWarehouseLocationPage(pageReqVO); + return success(new PageResult<>(buildWarehouseLocationRespVOList(pageResult.getList()), pageResult.getTotal())); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得库区精简列表", description = "可按仓库过滤") + public CommonResult> getWarehouseLocationSimpleList( + @Parameter(name = "warehouseId", description = "仓库编号") @RequestParam(value = "warehouseId", required = false) Long warehouseId) { + List list = locationService.getWarehouseLocationList(warehouseId); + return success(buildWarehouseLocationRespVOList(list)); + } + + @PutMapping("/update-by-location-id") + @Operation(summary = "批量设置库区下所有库位的混放规则") + @PreAuthorize("@ss.hasPermission('mes:wm-warehouse:update')") + public CommonResult updateAreaByLocationId( + @RequestParam("locationId") Long locationId, + @RequestParam(value = "allowItemMixing", required = false) Boolean allowItemMixing, + @RequestParam(value = "allowBatchMixing", required = false) Boolean allowBatchMixing) { + areaService.updateByLocationId(locationId, allowItemMixing, allowBatchMixing); + return success(true); + } + + // ==================== 拼接 VO ==================== + + /** + * 批量构建库区响应 VO 列表(填充仓库名称) + * + * @param list 库区列表 + * @return 响应 VO 列表 + */ + private List buildWarehouseLocationRespVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + // 1. 获得仓库信息 + Map warehouseMap = warehouseService.getWarehouseMap(convertSet(list, MesWmWarehouseLocationDO::getWarehouseId)); + // 2. 构建结果 + return BeanUtils.toBean(list, MesWmWarehouseLocationRespVO.class, vo -> + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()))); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehousePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehousePageReqVO.java new file mode 100644 index 000000000..e6861e3df --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehousePageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 仓库分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmWarehousePageReqVO extends PageParam { + + @Schema(description = "仓库编码", example = "WH001") + private String code; + + @Schema(description = "仓库名称", example = "原料仓") + private String name; + + @Schema(description = "是否冻结", example = "false") + private Boolean frozen; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseRespVO.java new file mode 100644 index 000000000..6c85e3bd2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 仓库 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmWarehouseRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "仓库编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WH001") + @ExcelProperty("仓库编码") + private String code; + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料仓") + @ExcelProperty("仓库名称") + private String name; + + @Schema(description = "仓库地址", example = "A 区一号楼") + @ExcelProperty("仓库地址") + private String address; + + @Schema(description = "面积", example = "1200.50") + @ExcelProperty("面积") + private BigDecimal area; + + @Schema(description = "负责人用户编号", example = "1") + private Long chargeUserId; + + @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @ExcelProperty("是否冻结") + private Boolean frozen; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseSaveReqVO.java new file mode 100644 index 000000000..a05c861b7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseSaveReqVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 仓库新增/修改 Request VO") +@Data +public class MesWmWarehouseSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "仓库编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "WH001") + @NotEmpty(message = "仓库编码不能为空") + private String code; + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料仓") + @NotEmpty(message = "仓库名称不能为空") + private String name; + + @Schema(description = "仓库地址", example = "A 区一号楼") + private String address; + + @Schema(description = "面积", example = "1200.50") + private BigDecimal area; + + @Schema(description = "负责人用户编号", example = "1") + private Long chargeUserId; + + @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "是否冻结不能为空") + private Boolean frozen; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaPageReqVO.java new file mode 100644 index 000000000..2a406536d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaPageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 库位分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmWarehouseAreaPageReqVO extends PageParam { + + @Schema(description = "库位编码", example = "A001") + private String code; + + @Schema(description = "库位名称", example = "默认库位") + private String name; + + @Schema(description = "库区编号", example = "1") + private Long locationId; + + @Schema(description = "位置 X", example = "1") + private Integer positionX; + + @Schema(description = "位置 Y", example = "1") + private Integer positionY; + + @Schema(description = "位置 Z", example = "1") + private Integer positionZ; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaRespVO.java new file mode 100644 index 000000000..0cd11b048 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaRespVO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 库位 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmWarehouseAreaRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "库位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A001") + @ExcelProperty("库位编码") + private String code; + + @Schema(description = "库位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "默认库位") + @ExcelProperty("库位名称") + private String name; + + @Schema(description = "库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long locationId; + + @Schema(description = "库区名称", example = "原料区") + @ExcelProperty("库区名称") + private String locationName; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原料仓") + @ExcelProperty("仓库名称") + private String warehouseName; + + @Schema(description = "面积", example = "20.00") + @ExcelProperty("面积") + private BigDecimal area; + + @Schema(description = "最大载重", example = "1000.00") + @ExcelProperty("最大载重") + private BigDecimal maxLoad; + + @Schema(description = "位置 X", example = "1") + @ExcelProperty("位置 X") + private Integer positionX; + + @Schema(description = "位置 Y", example = "1") + @ExcelProperty("位置 Y") + private Integer positionY; + + @Schema(description = "位置 Z", example = "1") + @ExcelProperty("位置 Z") + private Integer positionZ; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("状态") + private Integer status; + + @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @ExcelProperty("是否冻结") + private Boolean frozen; + + @Schema(description = "是否允许物料混放", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty("允许物料混放") + private Boolean allowItemMixing; + + @Schema(description = "是否允许批次混放", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @ExcelProperty("允许批次混放") + private Boolean allowBatchMixing; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaSaveReqVO.java new file mode 100644 index 000000000..60322e181 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaSaveReqVO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 库位新增/修改 Request VO") +@Data +public class MesWmWarehouseAreaSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "库位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A001") + @NotEmpty(message = "库位编码不能为空") + private String code; + + @Schema(description = "库位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "默认库位") + @NotEmpty(message = "库位名称不能为空") + private String name; + + @Schema(description = "库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库区不能为空") + private Long locationId; + + @Schema(description = "面积", example = "20.00") + private BigDecimal area; + + @Schema(description = "最大载重", example = "1000.00") + private BigDecimal maxLoad; + + @Schema(description = "位置 X", example = "1") + private Integer positionX; + + @Schema(description = "位置 Y", example = "1") + private Integer positionY; + + @Schema(description = "位置 Z", example = "1") + private Integer positionZ; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "是否冻结不能为空") + private Boolean frozen; + + @Schema(description = "是否允许物料混放", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否允许物料混放不能为空") + private Boolean allowItemMixing; + + @Schema(description = "是否允许批次混放", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否允许批次混放不能为空") + private Boolean allowBatchMixing; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationPageReqVO.java new file mode 100644 index 000000000..a1754c3f5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - MES 库区分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesWmWarehouseLocationPageReqVO extends PageParam { + + @Schema(description = "库区编码", example = "L001") + private String code; + + @Schema(description = "库区名称", example = "原料区") + private String name; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java new file mode 100644 index 000000000..c593a33bc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location; + +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 库区 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesWmWarehouseLocationRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "库区编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "L001") + @ExcelProperty("库区编码") + private String code; + + @Schema(description = "库区名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料区") + @ExcelProperty("库区名称") + private String name; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "原料仓") + @ExcelProperty("仓库名称") + private String warehouseName; + + @Schema(description = "面积", example = "500.00") + @ExcelProperty("面积") + private BigDecimal area; + + @Schema(description = "库位管理状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("库位管理状态") + private Integer areaStatus; + + @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @ExcelProperty("是否冻结") + private Boolean frozen; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationSaveReqVO.java new file mode 100644 index 000000000..d3bb7a5cf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationSaveReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 库区新增/修改 Request VO") +@Data +public class MesWmWarehouseLocationSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "库区编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "L001") + @NotEmpty(message = "库区编码不能为空") + private String code; + + @Schema(description = "库区名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料区") + @NotEmpty(message = "库区名称不能为空") + private String name; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库不能为空") + private Long warehouseId; + + @Schema(description = "面积", example = "500.00") + private BigDecimal area; + + @Schema(description = "库位管理状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "库位管理状态不能为空") + private Integer areaStatus; + + @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "是否冻结不能为空") + private Boolean frozen; + + @Schema(description = "备注", example = "备注") + private String remark; + + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/package-info.java new file mode 100644 index 000000000..d760e5d57 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.mes.controller; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/holiday/MesCalHolidayDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/holiday/MesCalHolidayDO.java new file mode 100644 index 000000000..649a3613e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/holiday/MesCalHolidayDO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday; + +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_cal_holiday") +@KeySequence("mes_cal_holiday_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesCalHolidayDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 日期 + */ + private LocalDateTime day; + /** + * 日期类型 + * + * 字典 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_CAL_HOLIDAY_TYPE} + */ + private Integer type; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanDO.java new file mode 100644 index 000000000..5ead025bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanDO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalPlanStatusEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +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_cal_plan") +@KeySequence("mes_cal_plan_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesCalPlanDO extends BaseDO { + + /** + * 计划编号 + */ + @TableId + private Long id; + /** + * 计划编码 + */ + private String code; + /** + * 计划名称 + */ + private String name; + /** + * 班组类型 + */ + private Integer calendarType; + /** + * 开始日期 + */ + private LocalDateTime startDate; + /** + * 结束日期 + */ + private LocalDateTime endDate; + /** + * 轮班方式 + * + * 枚举 {@link MesCalShiftTypeEnum} + */ + private Integer shiftType; + /** + * 倒班方式 + * + * 枚举 {@link MesCalShiftMethodEnum} + */ + private Integer shiftMethod; + /** + * 倒班天数 + */ + private Integer shiftCount; + /** + * 状态 + * + * 枚举 {@link MesCalPlanStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanShiftDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanShiftDO.java new file mode 100644 index 000000000..f29f43def --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanShiftDO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan; + +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.*; + +/** + * MES 计划班次 DO + * + * @author 芋道源码 + */ +@TableName("mes_cal_plan_shift") +@KeySequence("mes_cal_plan_shift_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesCalPlanShiftDO extends BaseDO { + + /** + * 班次编号 + */ + @TableId + private Long id; + /** + * 排班计划编号 + * + * 关联 {@link MesCalPlanDO#getId()} + */ + private Long planId; + /** + * 显示顺序 + */ + private Integer sort; + /** + * 班次名称 + */ + private String name; + /** + * 开始时间(HH:mm 格式) + */ + private String startTime; + /** + * 结束时间(HH:mm 格式) + */ + private String endTime; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanTeamDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanTeamDO.java new file mode 100644 index 000000000..94ce2ceb9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanTeamDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 计划班组关联 DO + * + * @author 芋道源码 + */ +@TableName("mes_cal_plan_team") +@KeySequence("mes_cal_plan_team_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesCalPlanTeamDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 排班计划编号 + * + * 关联 {@link MesCalPlanDO#getId()} + */ + private Long planId; + /** + * 班组编号 + * + * 关联 {@link MesCalTeamDO#getId()} + */ + private Long teamId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamDO.java new file mode 100644 index 000000000..fba0ccc05 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamDO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.cal.team; + +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.*; + +/** + * MES 班组 DO + * + * @author 芋道源码 + */ +@TableName("mes_cal_team") +@KeySequence("mes_cal_team_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesCalTeamDO extends BaseDO { + + /** + * 班组编号 + */ + @TableId + private Long id; + /** + * 班组编码 + */ + private String code; + /** + * 班组名称 + */ + private String name; + /** + * 班组类型 + */ + private Integer calendarType; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamMemberDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamMemberDO.java new file mode 100644 index 000000000..aa804245c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamMemberDO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.cal.team; + +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.*; + +/** + * MES 班组成员 DO + * + * @author 芋道源码 + */ +@TableName("mes_cal_team_member") +@KeySequence("mes_cal_team_member_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesCalTeamMemberDO extends BaseDO { + + /** + * 班组成员编号 + */ + @TableId + private Long id; + /** + * 班组编号 + * + * 关联 {@link MesCalTeamDO#getId()} + */ + private Long teamId; + /** + * 用户编号 + * + * 关联 system_users 表 + */ + private Long userId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamShiftDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamShiftDO.java new file mode 100644 index 000000000..12222768b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/team/MesCalTeamShiftDO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.cal.team; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +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_cal_team_shift") +@KeySequence("mes_cal_team_shift_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesCalTeamShiftDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 排班计划编号 + * + * 关联 {@link MesCalPlanDO#getId()} + */ + private Long planId; + /** + * 班组编号 + * + * 关联 {@link MesCalTeamDO#getId()} + */ + private Long teamId; + /** + * 班次编号 + * + * 关联 {@link MesCalPlanShiftDO#getId()} + */ + private Long shiftId; + /** + * 日期 + */ + private LocalDateTime day; + /** + * 排序 + */ + private Integer sort; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanDO.java new file mode 100644 index 000000000..1fa287b25 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanDO.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckPlanStatusEnum; +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_dv_check_plan") +@KeySequence("mes_dv_check_plan_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvCheckPlanDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 方案编码 + */ + private String code; + /** + * 方案名称 + */ + private String name; + /** + * 方案类型 + * + * 字典 {@link DictTypeConstants#MES_DV_SUBJECT_TYPE} + */ + private Integer type; + /** + * 开始日期 + */ + private LocalDateTime startDate; + /** + * 结束日期 + */ + private LocalDateTime endDate; + /** + * 周期类型 + * + * 字典 {@link DictTypeConstants#MES_DV_CYCLE_TYPE} + */ + private Integer cycleType; + /** + * 周期数量 + */ + private Integer cycleCount; + /** + * 状态 + * + * 枚举 {@link MesDvCheckPlanStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanMachineryDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanMachineryDO.java new file mode 100644 index 000000000..220405918 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanMachineryDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 点检保养方案设备 DO + * + * @author 芋道源码 + */ +@TableName("mes_dv_check_plan_machinery") +@KeySequence("mes_dv_check_plan_machinery_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvCheckPlanMachineryDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 方案编号 + * + * 关联 {@link MesDvCheckPlanDO#getId()} + */ + private Long planId; + /** + * 设备编号 + * + * 关联 {@link MesDvMachineryDO#getId()} + */ + private Long machineryId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanSubjectDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanSubjectDO.java new file mode 100644 index 000000000..af6fc253c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanSubjectDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 点检保养方案项目 DO + * + * @author 芋道源码 + */ +@TableName("mes_dv_check_plan_subject") +@KeySequence("mes_dv_check_plan_subject_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvCheckPlanSubjectDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 方案编号 + * + * 关联 {@link MesDvCheckPlanDO#getId()} + */ + private Long planId; + /** + * 项目编号 + * + * 关联 {@link MesDvSubjectDO#getId()} + */ + private Long subjectId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordDO.java new file mode 100644 index 000000000..8e66d5bca --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordDO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckRecordStatusEnum; +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_dv_check_record") +@KeySequence("mes_dv_check_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvCheckRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 点检计划编号 + * + * 关联 {@link MesDvCheckPlanDO#getId()} + */ + private Long planId; + /** + * 设备编号 + * + * 关联 {@link MesDvMachineryDO#getId()} + */ + private Long machineryId; + /** + * 点检时间 + */ + private LocalDateTime checkTime; + /** + * 点检人编号 + * + * 关联 AdminUserDO#getId() + */ + private Long userId; + /** + * 状态 + * + * 枚举 {@link MesDvCheckRecordStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordLineDO.java new file mode 100644 index 000000000..732c60fa7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordLineDO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckResultEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 设备点检记录明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_dv_check_record_line") +@KeySequence("mes_dv_check_record_line_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvCheckRecordLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 点检记录编号 + * + * 关联 {@link MesDvCheckRecordDO#getId()} + */ + private Long recordId; + /** + * 点检项目编号 + * + * 关联 {@link MesDvSubjectDO#getId()} + */ + private Long subjectId; + /** + * 点检结果 + * + * 枚举 {@link MesDvCheckResultEnum} + */ + private Integer checkStatus; + /** + * 异常描述 + * + * 仅 {@link #checkStatus} 为异常时使用 + */ + private String checkResult; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java new file mode 100644 index 000000000..940734dad --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery; + +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_dv_machinery") +@KeySequence("mes_dv_machinery_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvMachineryDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 设备编码 + */ + private String code; + /** + * 设备名称 + */ + private String name; + /** + * 品牌 + */ + private String brand; + /** + * 规格型号 + */ + private String spec; + /** + * 设备类型编号 + * + * 关联 {@link MesDvMachineryTypeDO#getId()} + */ + private Long machineryTypeId; + /** + * 所属车间编号 + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO#getId()} + */ + private Long workshopId; + /** + * 设备状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.dv.MesDvMachineryStatusEnum} + */ + private Integer status; + /** + * 最近保养时间 + */ + private LocalDateTime lastMaintenTime; + /** + * 最近点检时间 + */ + private LocalDateTime lastCheckTime; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryTypeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryTypeDO.java new file mode 100644 index 000000000..d88bd70d3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryTypeDO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery; + +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.*; + +/** + * MES 设备类型 DO + * + * @author 芋道源码 + */ +@TableName("mes_dv_machinery_type") +@KeySequence("mes_dv_machinery_type_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvMachineryTypeDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 类型编码 + */ + private String code; + /** + * 类型名称 + */ + private String name; + /** + * 父类型编号 + * + * 关联 {@link MesDvMachineryTypeDO#getId()} + */ + private Long parentId; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 显示排序 + */ + private Integer sort; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordDO.java new file mode 100644 index 000000000..555b6b5a3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordDO.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvMaintenRecordStatusEnum; +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_dv_mainten_record") +@KeySequence("mes_dv_mainten_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvMaintenRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 计划编号 + * + * 关联 {@link MesDvCheckPlanDO#getId()} + */ + private Long planId; + /** + * 设备编号 + * + * 关联 {@link MesDvMachineryDO#getId()} + */ + private Long machineryId; + /** + * 保养时间 + */ + private LocalDateTime maintenTime; + /** + * 用户编号 + * + * 关联 AdminUserDO#getId() + */ + private Long userId; + /** + * 状态 + * + * 枚举 {@link MesDvMaintenRecordStatusEnum} + * 字典类型 mes_mainten_record_status + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordLineDO.java new file mode 100644 index 000000000..224902da6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordLineDO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvMaintenStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 设备保养记录明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_dv_mainten_record_line") +@KeySequence("mes_dv_mainten_record_line_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvMaintenRecordLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 保养记录编号 + * + * 关联 {@link MesDvMaintenRecordDO#getId()} + */ + private Long recordId; + /** + * 项目编号 + * + * 关联 {@link MesDvSubjectDO#getId()} + */ + private Long subjectId; + /** + * 保养结果 + * + * 枚举 {@link MesDvMaintenStatusEnum} + * 字典类型 mes_mainten_status + */ + private Integer status; + /** + * 异常描述 + */ + private String result; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairDO.java new file mode 100644 index 000000000..25f7cca86 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairDO.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvRepairResultEnum; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvRepairStatusEnum; +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_dv_repair") +@KeySequence("mes_dv_repair_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvRepairDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 维修工单编码 + */ + private String code; + /** + * 维修工单名称 + */ + private String name; + /** + * 设备编号 + * + * 关联 {@link MesDvMachineryDO#getId()} + */ + private Long machineryId; + /** + * 报修日期 + */ + private LocalDateTime requireDate; + /** + * 维修完成日期 + */ + private LocalDateTime finishDate; + /** + * 验收日期 + */ + private LocalDateTime confirmDate; + /** + * 维修结果 + * + * 枚举 {@link MesDvRepairResultEnum} + */ + private Integer result; + /** + * 维修人用户编号 + * + * 关联 AdminUserDO#getId() + */ + private Long acceptedUserId; + /** + * 验收人用户编号 + * + * 关联 AdminUserDO#getId() + */ + private Long confirmUserId; + // DONE @芋艿:sourceDocType、sourceDocId、sourceDocCode 为预留字段,对齐:暂未使用 + /** + * 来源单据类型 + */ + private Integer sourceDocType; + /** + * 来源单据编号 + */ + private Long sourceDocId; + /** + * 来源单据编码 + */ + private String sourceDocCode; + /** + * 状态 + * + * 枚举 {@link MesDvRepairStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairLineDO.java new file mode 100644 index 000000000..9dcee4a95 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairLineDO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 维修工单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_dv_repair_line") +@KeySequence("mes_dv_repair_line_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvRepairLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 维修工单编号 + * + * 关联 {@link MesDvRepairDO#getId()} + */ + private Long repairId; + /** + * 点检保养项目编号 + * + * 关联 {@link MesDvSubjectDO#getId()} + */ + private Long subjectId; + /** + * 故障描述 + */ + private String malfunction; + /** + * 故障图片 URL + */ + private String malfunctionUrl; + /** + * 维修描述 + */ + private String description; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/subject/MesDvSubjectDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/subject/MesDvSubjectDO.java new file mode 100644 index 000000000..2e945567d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/subject/MesDvSubjectDO.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject; + +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.*; + +/** + * MES 点检保养项目 DO + * + * @author 芋道源码 + */ +@TableName("mes_dv_subject") +@KeySequence("mes_dv_subject_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesDvSubjectDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 项目编码 + */ + private String code; + /** + * 项目名称 + */ + private String name; + /** + * 项目类型 + * + * 字典类型 mes_dv_subject_type + */ + private Integer type; + /** + * 项目内容 + */ + private String content; + /** + * 标准 + */ + private String standard; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java new file mode 100644 index 000000000..a76fc5009 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode; + +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.*; + +/** + * MES 编码规则组成 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_auto_code_part") +@KeySequence("mes_md_auto_code_part_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdAutoCodePartDO extends BaseDO { + + /** + * 分段 ID + */ + @TableId + private Long id; + /** + * 规则 ID + * + * 关联 {@link MesMdAutoCodeRuleDO#getId()} + */ + private Long ruleId; + /** + * 分段序号 + */ + private Integer sort; + /** + * 分段长度 + */ + private Integer length; + /** + * 备注 + */ + private String remark; + /** + * 分段类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum} + */ + private Integer type; + + // ========== 当 MesMdAutoCodePartTypeEnum#INPUT_CHAR 时,使用 ========== + /** + * 固定字符 + */ + private String fixCharacter; + + // ========== 当 MesMdAutoCodePartTypeEnum#DATE 时,使用 ========== + /** + * 日期格式 + * + * 例如:yyyyMMdd、yyyyMM、HHmmss + */ + private String dateFormat; + + // ========== 当 MesMdAutoCodePartTypeEnum#SERIAL_NUMBER 时,使用 ========== + /** + * 流水号起始值 + */ + private Integer serialStartNo; + /** + * 流水号步长 + */ + private Integer serialStep; + /** + * 流水号是否循环 + */ + private Boolean cycleFlag; + /** + * 循环方式 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeCycleMethodEnum} + */ + private Integer cycleMethod; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java new file mode 100644 index 000000000..e2079e934 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 编码生成记录 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_auto_code_record") +@KeySequence("mes_md_auto_code_record_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdAutoCodeRecordDO extends BaseDO { + + /** + * 记录 ID + */ + @TableId + private Long id; + /** + * 规则 ID + * + * 关联 {@link MesMdAutoCodeRuleDO#getId()} + */ + private Long ruleId; + /** + * 生成的编码 + */ + private String result; + /** + * 传入的参数 + */ + private String inputChar; + /** + * 生成的流水号 + * + * 当规则组成中包含流水号分段({@link MesMdAutoCodePartTypeEnum#SERIAL_NUMBER})时记录,方便追溯和调试 + */ + private Long serialNo; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java new file mode 100644 index 000000000..c198f9b51 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode; + +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.*; + +/** + * MES 编码规则 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_auto_code_rule") +@KeySequence("mes_md_auto_code_rule_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdAutoCodeRuleDO extends BaseDO { + + /** + * 规则 ID + */ + @TableId + private Long id; + /** + * 规则编码 + */ + private String code; + /** + * 规则名称 + */ + private String name; + /** + * 描述 + */ + private String description; + /** + * 最大长度 + */ + private Integer maxLength; + /** + * 是否补齐 + */ + private Boolean padded; + /** + * 补齐字符 + */ + private String paddedChar; + /** + * 补齐方式 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePaddedMethodEnum} + */ + private Integer paddedMethod; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/client/MesMdClientDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/client/MesMdClientDO.java new file mode 100644 index 000000000..12ebb3e3c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/client/MesMdClientDO.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.client; + +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.*; + +/** + * MES 客户 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_client") +@KeySequence("mes_md_client_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdClientDO extends BaseDO { + + /** + * 客户编号 + */ + @TableId + private Long id; + /** + * 客户编码 + */ + private String code; + /** + * 客户名称 + */ + private String name; + /** + * 客户简称 + */ + private String nickname; + /** + * 客户英文名称 + */ + private String englishName; + /** + * 客户简介 + */ + private String description; + /** + * 客户LOGO地址 + */ + private String logo; + /** + * 客户类型 + * + * 字典 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_CLIENT_TYPE} + */ + private Integer type; + /** + * 客户地址 + */ + private String address; + /** + * 客户官网地址 + */ + private String website; + /** + * 客户邮箱地址 + */ + private String email; + /** + * 客户电话 + */ + private String telephone; + /** + * 联系人1 + */ + private String contact1Name; + /** + * 联系人1-电话 + */ + private String contact1Telephone; + /** + * 联系人1-邮箱 + */ + private String contact1Email; + /** + * 联系人2 + */ + private String contact2Name; + /** + * 联系人2-电话 + */ + private String contact2Telephone; + /** + * 联系人2-邮箱 + */ + private String contact2Email; + /** + * 统一社会信用代码 + */ + private String creditCode; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemBatchConfigDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemBatchConfigDO.java new file mode 100644 index 000000000..1096883fe --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemBatchConfigDO.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.item; + +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.*; + +/** + * MES 物料批次属性配置 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_item_batch_config") +@KeySequence("mes_md_item_batch_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdItemBatchConfigDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 批次属性-生产日期 + */ + private Boolean produceDateFlag; + /** + * 批次属性-有效期 + */ + private Boolean expireDateFlag; + /** + * 批次属性-入库日期 + */ + private Boolean receiptDateFlag; + /** + * 批次属性-供应商 + */ + private Boolean vendorFlag; + /** + * 批次属性-客户 + */ + private Boolean clientFlag; + /** + * 批次属性-销售订单编号 + */ + private Boolean salesOrderCodeFlag; + /** + * 批次属性-采购订单编号 + */ + private Boolean purchaseOrderCodeFlag; + /** + * 批次属性-生产工单 + */ + private Boolean workOrderFlag; + /** + * 批次属性-生产任务 + */ + private Boolean taskFlag; + /** + * 批次属性-工作站 + */ + private Boolean workstationFlag; + /** + * 批次属性-工具 + */ + private Boolean toolFlag; + /** + * 批次属性-模具 + */ + private Boolean moldFlag; + /** + * 批次属性-生产批号 + */ + private Boolean lotNumberFlag; + /** + * 批次属性-质量状态 + */ + private Boolean qualityStatusFlag; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemDO.java new file mode 100644 index 000000000..c1a969ca4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemDO.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.item; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 物料产品 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_item") +@KeySequence("mes_md_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdItemDO extends BaseDO { + + /** + * 物料编号 + */ + @TableId + private Long id; + /** + * 物料编码 + */ + private String code; + /** + * 物料名称 + */ + private String name; + /** + * 规格型号 + */ + private String specification; + /** + * 计量单位编号 + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long unitMeasureId; + /** + * 物料分类编号 + * + * 关联 {@link MesMdItemTypeDO#getId()} + */ + private Long itemTypeId; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 是否启用安全库存 + */ + private Boolean safeStockFlag; + /** + * 最低库存量 + */ + private BigDecimal minStock; + /** + * 最高库存量 + */ + private BigDecimal maxStock; + /** + * 是否高值物料 + */ + private Boolean highValue; + /** + * 是否启用批次管理 + */ + private Boolean batchFlag; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java new file mode 100644 index 000000000..c70933081 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.item; + +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.*; + +/** + * MES 物料产品分类 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_item_type") +@KeySequence("mes_md_item_type_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdItemTypeDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 分类编号 + */ + @TableId + private Long id; + /** + * 分类编码 + */ + private String code; + /** + * 分类名称 + */ + private String name; + /** + * 父分类编号 + */ + private Long parentId; + /** + * 物料/产品标识 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.MesMdItemTypeEnum} + */ + private String itemOrProduct; + /** + * 显示排序 + */ + private Integer sort; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductBomDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductBomDO.java new file mode 100644 index 000000000..77e6a47c7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductBomDO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.item; + +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.math.BigDecimal; + +/** + * MES 产品BOM DO + * + * @author 芋道源码 + */ +@TableName("mes_md_product_bom") +@KeySequence("mes_md_product_bom_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdProductBomDO extends BaseDO { + + /** + * BOM编号 + */ + @TableId + private Long id; + /** + * 物料产品编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * BOM物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long bomItemId; + /** + * 物料使用比例 + */ + private BigDecimal quantity; + /** + * 是否启用 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductSipDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductSipDO.java new file mode 100644 index 000000000..7080e80cf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductSipDO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.item; + +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.*; + +/** + * MES 产品SIP DO + * + * @author 芋道源码 + */ +@TableName("mes_md_product_sip") +@KeySequence("mes_md_product_sip_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdProductSipDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 物料产品编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 排列顺序 + */ + private Integer sort; + /** + * 工序编号 + */ + // TODO @芋艿:等 pro 工序模块实现后,补上 {@link} 关联 + private Long processId; + /** + * 标题 + */ + private String title; + /** + * 详细描述 + */ + private String description; + /** + * 图片地址 + */ + private String url; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductSopDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductSopDO.java new file mode 100644 index 000000000..0455034ea --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductSopDO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.item; + +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.*; + +/** + * MES 产品SOP DO + * + * @author 芋道源码 + */ +@TableName("mes_md_product_sop") +@KeySequence("mes_md_product_sop_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdProductSopDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 物料产品编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 排列顺序 + */ + private Integer sort; + /** + * 工序编号 + */ + private Long processId; + /** + * 标题 + */ + private String title; + /** + * 详细描述 + */ + private String description; + /** + * 图片地址 + */ + private String url; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/unitmeasure/MesMdUnitMeasureDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/unitmeasure/MesMdUnitMeasureDO.java new file mode 100644 index 000000000..06cd90f7d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/unitmeasure/MesMdUnitMeasureDO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure; + +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.math.BigDecimal; + +/** + * MES 计量单位 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_unit_measure") +@KeySequence("mes_md_unit_measure_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdUnitMeasureDO extends BaseDO { + + /** + * 单位编号 + */ + @TableId + private Long id; + /** + * 单位编码 + */ + private String code; + /** + * 单位名称 + */ + private String name; + /** + * 是否主单位 + */ + private Boolean primaryFlag; + /** + * 主单位编号 + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long primaryId; + /** + * 与主单位换算比例 + */ + private BigDecimal changeRate; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/vendor/MesMdVendorDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/vendor/MesMdVendorDO.java new file mode 100644 index 000000000..1a931a7c8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/vendor/MesMdVendorDO.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor; + +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.*; + +/** + * MES 供应商 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_vendor") +@KeySequence("mes_md_vendor_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdVendorDO extends BaseDO { + + /** + * 供应商编号 + */ + @TableId + private Long id; + /** + * 供应商编码 + */ + private String code; + /** + * 供应商名称 + */ + private String name; + /** + * 供应商简称 + */ + private String nickname; + /** + * 供应商英文名称 + */ + private String englishName; + /** + * 供应商简介 + */ + private String description; + /** + * 供应商LOGO地址 + */ + private String logo; + /** + * 供应商等级 + * + * 字典 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_VENDOR_LEVEL} + */ + private String level; + /** + * 供应商评分 + */ + private Integer score; + /** + * 供应商地址 + */ + private String address; + /** + * 供应商官网地址 + */ + private String website; + /** + * 供应商邮箱地址 + */ + private String email; + /** + * 供应商电话 + */ + private String telephone; + /** + * 联系人1 + */ + private String contact1Name; + /** + * 联系人1-电话 + */ + private String contact1Telephone; + /** + * 联系人1-邮箱 + */ + private String contact1Email; + /** + * 联系人2 + */ + private String contact2Name; + /** + * 联系人2-电话 + */ + private String contact2Telephone; + /** + * 联系人2-邮箱 + */ + private String contact2Email; + /** + * 统一社会信用代码 + */ + private String creditCode; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkshopDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkshopDO.java new file mode 100644 index 000000000..69cb5b86d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkshopDO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation; + +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.math.BigDecimal; + +/** + * MES 车间 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_workshop") +@KeySequence("mes_md_workshop_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdWorkshopDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 车间编码 + */ + private String code; + /** + * 车间名称 + */ + private String name; + /** + * 面积(平方米) + */ + private BigDecimal area; + /** + * 负责人用户编号 + * + * 关联 AdminUserDO 的 id + */ + private Long chargeUserId; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationDO.java new file mode 100644 index 000000000..bd3e80fa5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationDO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 工作站 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_workstation") +@KeySequence("mes_md_workstation_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdWorkstationDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工作站编码 + */ + private String code; + /** + * 工作站名称 + */ + private String name; + /** + * 工作站地点 + */ + private String address; + /** + * 所在车间编号 + * + * 关联 {@link MesMdWorkshopDO#getId()} + */ + private Long workshopId; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 线边库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationMachineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationMachineDO.java new file mode 100644 index 000000000..8a3a0b575 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationMachineDO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation; + +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.*; + +/** + * MES 设备资源 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_workstation_machine") +@KeySequence("mes_md_workstation_machine_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdWorkstationMachineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 设备编号 + * + * TODO @芋艿:等 dv 模块,关联设备表 + */ + private Long machineryId; + /** + * 数量 + */ + private Integer quantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationToolDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationToolDO.java new file mode 100644 index 000000000..61caa8637 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationToolDO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation; + +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.*; + +/** + * MES 工装夹具资源 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_workstation_tool") +@KeySequence("mes_md_workstation_tool_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdWorkstationToolDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 工具类型编号 + * + * TODO @芋艿:等 tm 模块,关联工具类型表 + */ + private Long toolTypeId; + /** + * 数量 + */ + private Integer quantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationWorkerDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationWorkerDO.java new file mode 100644 index 000000000..508cd8d1d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/workstation/MesMdWorkstationWorkerDO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation; + +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.*; + +/** + * MES 人力资源 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_workstation_worker") +@KeySequence("mes_md_workstation_worker_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdWorkstationWorkerDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 岗位编号 + * + * 关联 system_post 的 id + */ + private Long postId; + /** + * 数量 + */ + private Integer quantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonConfigDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonConfigDO.java new file mode 100644 index 000000000..c5c96250c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonConfigDO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.pro.MesProAndonLevelEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 安灯呼叫配置 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_andon_config") +@KeySequence("mes_pro_andon_config_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProAndonConfigDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 呼叫原因 + */ + private String reason; + /** + * 级别 + * + * 枚举 {@link MesProAndonLevelEnum} + */ + private Integer level; + /** + * 处置人角色编号 + * + * 关联 system_role#id + */ + private Long handlerRoleId; + /** + * 处置人编号 + * + * 关联 system_users#id + */ + private Long handlerUserId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonRecordDO.java new file mode 100644 index 000000000..663d3b8d8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonRecordDO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.enums.pro.MesProAndonLevelEnum; +import cn.iocoder.yudao.module.mes.enums.pro.MesProAndonStatusEnum; +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_andon_record") +@KeySequence("mes_pro_andon_record_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProAndonRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 安灯配置编号 + * + * 关联 {@link MesProAndonConfigDO#getId()} + */ + private Long configId; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 发起用户编号 + * + * 关联 system_users#id + */ + private Long userId; + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 呼叫原因(快照值,不随配置变更) + */ + private String reason; + /** + * 级别(快照值) + * + * 枚举 {@link MesProAndonLevelEnum} + */ + private Integer level; + /** + * 处置状态 + * + * 枚举 {@link MesProAndonStatusEnum} + */ + private Integer status; + /** + * 处置时间 + */ + private LocalDateTime handleTime; + /** + * 处置人编号 + * + * 关联 system_users#id + */ + private Long handlerUserId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardDO.java new file mode 100644 index 000000000..750ad47d8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardDO.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.card; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 生产流转卡 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_card") +@KeySequence("mes_pro_card_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProCardDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 流转卡编码 + */ + private String code; + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 产品物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 批次号 + */ + private String batchCode; + /** + * 流转数量 + */ + private BigDecimal transferedQuantity; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardProcessDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardProcessDO.java new file mode 100644 index 000000000..4bdf9c8da --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardProcessDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.card; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 流转卡工序记录 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_card_process") +@KeySequence("mes_pro_card_process_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProCardProcessDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 流转卡编号 + * + * 关联 {@link MesProCardDO#getId()} + */ + private Long cardId; + /** + * 序号 + */ + private Integer sort; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 进入工序时间 + */ + private LocalDateTime inputTime; + /** + * 出工序时间 + */ + private LocalDateTime outputTime; + /** + * 投入数量 + */ + private BigDecimal inputQuantity; + /** + * 产出数量 + */ + private BigDecimal outputQuantity; + /** + * 不合格品数量 + */ + private BigDecimal unqualifiedQuantity; + /** + * 工位编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 操作人编号 + * + * 关联 AdminUserDO#getId() + */ + private Long userId; + /** + * 过程检验单编号 + * + * TODO @芋艿:关联 mes_qc_ipqc 表,等 IPQC 模块迁移后再对接 + */ + private Long ipqcId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java new file mode 100644 index 000000000..840d2da06 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum; +import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 生产报工 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_feedback") +@KeySequence("mes_pro_feedback_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProFeedbackDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 报工单编号 + */ + private String code; + /** + * 报工类型 + * + * 枚举 {@link MesProFeedbackTypeEnum} + */ + private Integer type; + // TODO @芋艿:这个字段,暂时没使用到; + /** + * 报工途径 + * + * 字典类型 mes_pro_feedback_channel + */ + private String channel; + /** + * 报工时间 + */ + private LocalDateTime feedbackTime; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 工艺路线编号 + * + * 关联 {@link MesProRouteDO#getId()} + */ + private Long routeId; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + // TODO @芋艿:这里待关联; + /** + * 生产任务编号 + */ + private Long taskId; + /** + * 产品物料编号(冗余自任务) + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 过期日期 + */ + private LocalDateTime expireDate; + /** + * 生产批号 + * + * TODO @芋艿:预留字段,当前未启用 + */ + private String lotNumber; + /** + * 排产数量 + */ + private BigDecimal scheduledQuantity; + /** + * 本次报工数量 + */ + private BigDecimal feedbackQuantity; + /** + * 合格品数量 + */ + private BigDecimal qualifiedQuantity; + /** + * 不良品数量 + */ + private BigDecimal unqualifiedQuantity; + /** + * 待检测数量 + */ + private BigDecimal uncheckQuantity; + /** + * 工废数量 + */ + private BigDecimal laborScrapQuantity; + /** + * 料废数量 + */ + private BigDecimal materialScrapQuantity; + /** + * 其他废品数量 + */ + private BigDecimal otherScrapQuantity; + /** + * 报工用户编号 + * + * 关联 AdminUserDO#getId() + */ + private Long feedbackUserId; + /** + * 审核用户编号 + * + * 关联 AdminUserDO#getId() + */ + private Long approveUserId; + /** + * 状态 + * + * 枚举 {@link MesProFeedbackStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/process/MesProProcessContentDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/process/MesProProcessContentDO.java new file mode 100644 index 000000000..4cee957d5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/process/MesProProcessContentDO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.process; + +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.*; + +/** + * MES 生产工序内容 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_process_content") +@KeySequence("mes_pro_process_content_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProProcessContentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 顺序编号 + */ + private Integer sort; + /** + * 步骤说明 + */ + private String content; + /** + * 辅助设备 + */ + private String device; + /** + * 辅助材料 + */ + private String material; + /** + * 材料文档 URL + */ + private String docUrl; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/process/MesProProcessDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/process/MesProProcessDO.java new file mode 100644 index 000000000..c4bd6e11b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/process/MesProProcessDO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.process; + +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.*; + +/** + * MES 生产工序 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_process") +@KeySequence("mes_pro_process_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProProcessDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工序编码 + */ + private String code; + /** + * 工序名称 + */ + private String name; + /** + * 工艺要求 + */ + private String attention; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteDO.java new file mode 100644 index 000000000..a6bc13d49 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteDO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.route; + +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.*; + +/** + * MES 工艺路线 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_route") +@KeySequence("mes_pro_route_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProRouteDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工艺路线编码 + */ + private String code; + /** + * 工艺路线名称 + */ + private String name; + /** + * 工艺路线说明 + */ + private String description; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProcessDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProcessDO.java new file mode 100644 index 000000000..93a66a2a6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProcessDO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.route; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 工艺路线工序 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_route_process") +@KeySequence("mes_pro_route_process_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProRouteProcessDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工艺路线编号 + * + * 关联 {@link MesProRouteDO#getId()} + */ + private Long routeId; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 序号 + */ + private Integer sort; + /** + * 下一道工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long nextProcessId; + /** + * 与下一道工序关系 + * + * 字典 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_PRO_LINK_TYPE} + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.pro.MesProLinkTypeEnum} + */ + private Integer linkType; + /** + * 准备时间(分钟) + */ + private Integer prepareTime; + /** + * 等待时间(分钟) + */ + private Integer waitTime; + /** + * 甘特图显示颜色 + */ + private String colorCode; + /** + * 是否关键工序 + */ + private Boolean keyFlag; + /** + * 是否质检工序 + */ + private Boolean checkFlag; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProductBomDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProductBomDO.java new file mode 100644 index 000000000..68cd8a469 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProductBomDO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.route; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 工艺路线产品 BOM DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_route_product_bom") +@KeySequence("mes_pro_route_product_bom_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProRouteProductBomDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工艺路线编号 + * + * 关联 {@link MesProRouteDO#getId()} + */ + private Long routeId; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 产品物料编号 + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO#getId()} + */ + private Long productId; + /** + * BOM 物料编号 + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 用料比例 + */ + private BigDecimal quantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProductDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProductDO.java new file mode 100644 index 000000000..a73ed9f55 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProductDO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.route; + +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.math.BigDecimal; + +/** + * MES 工艺路线产品 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_route_product") +@KeySequence("mes_pro_route_product_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProRouteProductDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工艺路线编号 + * + * 关联 {@link MesProRouteDO#getId()} + */ + private Long routeId; + /** + * 产品物料编号 + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 生产数量 + */ + private Integer quantity; + /** + * 生产用时 + */ + private BigDecimal productionTime; + /** + * 时间单位 + * + * 字典 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_TIME_UNIT_TYPE} + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.pro.MesTimeUnitTypeEnum} + */ + private String timeUnitType; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java new file mode 100644 index 000000000..1a14001b5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.task; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 生产任务 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_task") +@KeySequence("mes_pro_task_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProTaskDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 任务编码 + */ + private String code; + /** + * 任务名称 + */ + private String name; + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 工艺路线编号 + * + * 关联 {@link MesProRouteDO#getId()} + */ + private Long routeId; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 产品物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + + /** + * 排产数量 + */ + private BigDecimal quantity; + /** + * 已生产数量 + */ + private BigDecimal producedQuantity; + /** + * 合格品数量 + */ + private BigDecimal qualifyQuantity; + /** + * 不良品数量 + */ + private BigDecimal unqualifyQuantity; + /** + * 调整数量 + */ + private BigDecimal changedQuantity; + + /** + * 客户编号 + * + * 关联 {@link MesMdClientDO#getId()} + */ + private Long clientId; + /** + * 开始生产时间 + */ + private LocalDateTime startTime; + /** + * 生产时长(工作日,1=8小时) + */ + private Integer duration; + /** + * 结束生产时间 + */ + private LocalDateTime endTime; + /** + * 甘特图显示颜色 + */ + private String colorCode; + /** + * 完成日期 + */ + private LocalDateTime finishDate; + /** + * 取消日期 + */ + private LocalDateTime cancelDate; + + /** + * 任务状态 + * + * 枚举 {@link MesProTaskStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskIssueDO.java new file mode 100644 index 000000000..54b57a48c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskIssueDO.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.task; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +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.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 生产任务投料 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_task_issue") +@KeySequence("mes_pro_task_issue_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProTaskIssueDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 生产任务编号 + * + * 关联 {@link MesProTaskDO#getId()} + */ + private Long taskId; + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 来源单据编号 + */ + private Long sourceDocId; + /** + * 来源单据编码 + */ + private String sourceDocCode; + /** + * 来源单据类型 + */ + private String sourceDocType; + /** + * 投料批次 + */ + private String batchCode; + /** + * 来源单据行编号 + */ + private Long sourceLineId; + /** + * 产品物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 单位编号 + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long unitMeasureId; + /** + * 总投料数量 + */ + private BigDecimal issuedQuantity; + /** + * 当前可用数量 + */ + private BigDecimal availableQuantity; + /** + * 当前使用数量 + */ + private BigDecimal usedQuantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderBomDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderBomDO.java new file mode 100644 index 000000000..db63e65bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderBomDO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 生产工单 BOM DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_work_order_bom") +@KeySequence("mes_pro_work_order_bom_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProWorkOrderBomDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * BOM 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 预计使用量 + */ + private BigDecimal quantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java new file mode 100644 index 000000000..6ff101a7c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderSourceTypeEnum; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 生产工单 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_work_order") +@KeySequence("mes_pro_work_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProWorkOrderDO extends BaseDO { + + /** + * 父工单编号,空值 + */ + public static final Long PARENT_ID_NULL = 0L; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工单编码 + */ + private String code; + /** + * 工单名称 + */ + private String name; + /** + * 工单类型 + * + * 枚举 {@link MesProWorkOrderTypeEnum} + */ + private Integer type; + /** + * 来源类型 + * + * 枚举 {@link MesProWorkOrderSourceTypeEnum} + */ + private Integer orderSourceType; + /** + * 来源单据编号 + */ + private String orderSourceCode; + /** + * 产品编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long productId; + /** + * 生产数量 + */ + private BigDecimal quantity; + /** + * 已生产数量 + */ + private BigDecimal quantityProduced; + /** + * 调整数量 + */ + private BigDecimal quantityChanged; + /** + * 已排产数量 + */ + private BigDecimal quantityScheduled; + /** + * 客户编号 + * + * 关联 {@link MesMdClientDO#getId()} + */ + private Long clientId; + /** + * 供应商编号 + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 批次号 + */ + private String batchCode; + /** + * 需求日期 + */ + private LocalDateTime requestDate; + /** + * 父工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long parentId; + /** + * 完成时间 + */ + private LocalDateTime finishDate; + /** + * 取消时间 + */ + private LocalDateTime cancelDate; + /** + * 工单状态 + * + * 枚举 {@link MesProWorkOrderStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordDO.java new file mode 100644 index 000000000..43d755b9c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordDO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * MES 用户工作站绑定关系(当前快照) DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_work_record") +@KeySequence("mes_pro_work_record_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProWorkRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 用户编号 + * + * 关联 AdminUserDO#getId() + */ + private Long userId; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 当前状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.pro.MesProWorkRecordTypeEnum} + */ + private Integer type; + /** + * 上工时间 + */ + private LocalDateTime clockInTime; + /** + * 下工时间 + */ + private LocalDateTime clockOutTime; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordLogDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordLogDO.java new file mode 100644 index 000000000..84cfcd962 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordLogDO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkRecordTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 上下工记录流水 DO + * + * @author 芋道源码 + */ +@TableName("mes_pro_work_record_log") +@KeySequence("mes_pro_work_record_log_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesProWorkRecordLogDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 用户编号 + * + * 关联 AdminUserDO#getId() + */ + private Long userId; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 操作类型 + * + * 枚举 {@link MesProWorkRecordTypeEnum} + */ + private Integer type; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defect/MesQcDefectDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defect/MesQcDefectDO.java new file mode 100644 index 000000000..ee835c7e4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defect/MesQcDefectDO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect; + +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.*; + +/** + * MES 缺陷类型 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_defect") +@KeySequence("mes_qc_defect_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcDefectDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 缺陷编码 + */ + private String code; + /** + * 缺陷描述 + */ + private String name; + /** + * 检测项类型 + * + * 字典类型 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_DEFECT_TYPE} + */ + private String type; + /** + * 缺陷等级 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum} + */ + private Integer level; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defectrecord/MesQcDefectRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defectrecord/MesQcDefectRecordDO.java new file mode 100644 index 000000000..51d1836ea --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defectrecord/MesQcDefectRecordDO.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcLineDO; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 质检缺陷记录 DO + * + * 通用缺陷记录表,通过 {@link #qcType} 区分检验类型(IQC、IPQC、OQC、RQC),多模块复用 + * + * @author 芋道源码 + */ +@TableName("mes_qc_defect_record") +@KeySequence("mes_qc_defect_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcDefectRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 检验类型 + * + * 枚举 {@link MesQcTypeEnum} + */ + private Integer qcType; + /** + * 检验单 ID + * + * 关联 {@link MesQcIqcDO#getId()} + * 关联 {@link MesQcIpqcDO#getId()} + */ + private Long qcId; + /** + * 检验行 ID + * + * 关联 {@link MesQcIqcLineDO#getId()} + * 关联 {@link MesQcIpqcLineDO#getId()} + */ + private Long lineId; + /** + * 缺陷描述 + */ + private String name; + /** + * 缺陷等级 + * + * 枚举 {@link MesQcDefectLevelEnum} + */ + private Integer level; + /** + * 缺陷数量 + */ + private Integer quantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicator/MesQcIndicatorDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicator/MesQcIndicatorDO.java new file mode 100644 index 000000000..a338ba356 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicator/MesQcIndicatorDO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator; + +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.*; + +/** + * MES 质检指标 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_indicator") +@KeySequence("mes_qc_indicator_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcIndicatorDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 检测项编码 + */ + private String code; + /** + * 检测项名称 + */ + private String name; + /** + * 检测项类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_INDICATOR_TYPE} + */ + private String type; + /** + * 检测工具 + */ + private String tool; + /** + * 结果值类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum} + */ + private Integer resultType; + /** + * 结果值属性 + * + * 1. FILE 时:存 IMG/FILE + * 2. DICT 时:存字典类型名 + */ + private String resultSpecification; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDO.java new file mode 100644 index 000000000..cb8343a63 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 检验结果记录 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_indicator_result") +@KeySequence("mes_qc_indicator_result_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcIndicatorResultDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 样品编号 + */ + private String code; + /** + * 关联质检单 ID(IQC/IPQC/OQC/RQC 的 id) + * + * 关联 IQC {@link MesQcIqcDO#getId()} + * 关联 IPQC {@link MesQcIpqcDO#getId()} + * 关联 OQC {@link MesQcOqcDO#getId()} + * 关联 RQC {@link MesQcRqcDO#getId()} + */ + private Long qcId; + /** + * 质检类型 + * + * 枚举 {@link MesQcTypeEnum} + */ + private Integer qcType; + /** + * 产品物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 物资 SN + */ + private String sn; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDetailDO.java new file mode 100644 index 000000000..e8dba6882 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDetailDO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 检验结果明细记录 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_indicator_result_detail") +@KeySequence("mes_qc_indicator_result_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcIndicatorResultDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 关联检验结果 ID + * + * 关联 {@link MesQcIndicatorResultDO#getId()} + */ + private Long resultId; + /** + * 检测指标 ID + * + * 关联 {@link MesQcIndicatorDO#getId()} + */ + private Long indicatorId; + /** + * 检测值(统一存为字符串) + */ + private String value; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java new file mode 100644 index 000000000..53e9222bc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java @@ -0,0 +1,206 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 过程检验单(IPQC, In-Process Quality Control) DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_ipqc") +@KeySequence("mes_qc_ipqc_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcIpqcDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 检验单编号 + */ + private String code; + /** + * 检验单名称 + */ + private String name; + /** + * IPQC 检验类型 + * + * 字典 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_IPQC_TYPE} + */ + private Integer type; + /** + * 检验模板 ID + * + * 关联 {@link MesQcTemplateDO#getId()} + */ + private Long templateId; + + // ========== 来源单据 ========== + + /** + * 来源单据类型 + * + * 枚举 {@link MesQcSourceDocTypeEnum} + */ + private Integer sourceDocType; + /** + * 来源单据 ID + * + * 关联:根据 {@link #sourceDocType} 不同: + * 1. {@link MesQcSourceDocTypeEnum#PRO_FEEDBACK} 时,关联 {@link MesProFeedbackDO#getId()} + */ + private Long sourceDocId; + /** + * 来源单据行 ID + * + * 关联:根据 {@link #sourceDocType} 不同: + * 1. {@link MesQcSourceDocTypeEnum#PRO_FEEDBACK} 时,关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO#getId()} + */ + private Long sourceLineId; + /** + * 来源单据编号(冗余) + */ + private String sourceDocCode; + + // ========== 生产关联 ========== + + /** + * 生产工单 ID + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 生产任务 ID + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO#getId()} + */ + private Long taskId; + /** + * 工位 ID + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 工序 ID + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO#getId()} + */ + private Long processId; + + // ========== 物料 ========== + + /** + * 产品物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + + // ========== 数量 ========== + + /** + * 检测数量 + */ + private BigDecimal checkQuantity; + /** + * 合格品数量 + */ + private BigDecimal qualifiedQuantity; + /** + * 不合格品数量 + */ + private BigDecimal unqualifiedQuantity; + /** + * 工废数量 + */ + private BigDecimal laborScrapQuantity; + /** + * 料废数量 + */ + private BigDecimal materialScrapQuantity; + /** + * 其他废品数量 + */ + private BigDecimal otherScrapQuantity; + + // ========== 缺陷统计 ========== + + /** + * 致命缺陷率(%) + */ + private BigDecimal criticalRate; + /** + * 严重缺陷率(%) + */ + private BigDecimal majorRate; + /** + * 轻微缺陷率(%) + */ + private BigDecimal minorRate; + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + + // ========== 检验 ========== + + /** + * 检测结果 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum} + */ + private Integer checkResult; + /** + * 检测日期 + */ + private LocalDateTime inspectDate; + /** + * 检测人员用户 ID + * + * 关联 AdminUserDO 的 id + */ + private Long inspectorUserId; + /** + * 状态 + * + * 枚举 {@link MesQcStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcLineDO.java new file mode 100644 index 000000000..b9b4b1d16 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcLineDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 过程检验单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_ipqc_line") +@KeySequence("mes_qc_ipqc_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcIpqcLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 过程检验单 ID + * + * 关联 {@link MesQcIpqcDO#getId()} + */ + private Long ipqcId; + /** + * 检测指标 ID + * + * 关联 {@link MesQcIndicatorDO#getId()} + */ + private Long indicatorId; + /** + * 检测工具 + * + * 冗余 {@link MesQcIndicatorDO#getTool()} + */ + private String tool; + /** + * 检测方法 + */ + private String checkMethod; + /** + * 标准值 + */ + private BigDecimal standardValue; + /** + * 计量单位 ID + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long unitMeasureId; + /** + * 误差上限 + */ + private BigDecimal maxThreshold; + /** + * 误差下限 + */ + private BigDecimal minThreshold; + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java new file mode 100644 index 000000000..d0a02017b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java @@ -0,0 +1,183 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 来料检验单(IQC, Incoming Quality Control) DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_iqc") +@KeySequence("mes_qc_iqc_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcIqcDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 检验单编号 + */ + private String code; + /** + * 检验单名称 + */ + private String name; + /** + * 检验模板 ID + * + * 关联 {@link MesQcTemplateDO#getId()} + */ + private Long templateId; + + // ========== 来源单据 ========== + + /** + * 来源单据类型 + * + * 枚举 {@link MesQcSourceDocTypeEnum} + */ + private Integer sourceDocType; + /** + * 来源单据 ID + * + * 关联:根据 {@link #sourceDocType} 不同: + * 1. {@link MesQcSourceDocTypeEnum#ARRIVAL_NOTICE} 时,关联 {@link MesWmArrivalNoticeDO#getId()} + */ + private Long sourceDocId; + /** + * 来源单据行 ID + * + * 关联:根据 {@link #sourceDocType} 不同: + * 1. {@link MesQcSourceDocTypeEnum#ARRIVAL_NOTICE} 时,关联 {@link MesWmArrivalNoticeLineDO#getId()} + */ + private Long sourceLineId; + /** + * 来源单据编号(冗余) + */ + private String sourceDocCode; + + // ========== 供应商 ========== + + /** + * 供应商 ID + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 供应商批次号 + */ + private String vendorBatch; + + // ========== 物料 ========== + + /** + * 产品物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + + // ========== 数量 ========== + + /** + * 本次接收数量 + */ + private BigDecimal receivedQuantity; + /** + * 本次检测数量 + */ + private BigDecimal checkQuantity; + /** + * 合格品数量 + */ + private BigDecimal qualifiedQuantity; + /** + * 不合格品数量 + */ + private BigDecimal unqualifiedQuantity; + + // ========== 缺陷统计 ========== + + /** + * 致命缺陷率(%) + */ + private BigDecimal criticalRate; + /** + * 严重缺陷率(%) + */ + private BigDecimal majorRate; + /** + * 轻微缺陷率(%) + */ + private BigDecimal minorRate; + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + + // ========== 检验 ========== + + /** + * 检测结果 + * + * 枚举 {@link MesQcCheckResultEnum} + */ + private Integer checkResult; + /** + * 来料日期 + */ + private LocalDateTime receiveDate; + /** + * 检测日期 + */ + private LocalDateTime inspectDate; + /** + * 检测人员用户 ID + * + * 关联 AdminUserDO 的 id + */ + private Long inspectorUserId; + /** + * 状态 + * + * 枚举 {@link MesQcStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcLineDO.java new file mode 100644 index 000000000..3d81e16cc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcLineDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 来料检验单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_iqc_line") +@KeySequence("mes_qc_iqc_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcIqcLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 来料检验单 ID + * + * 关联 {@link MesQcIqcDO#getId()} + */ + private Long iqcId; + /** + * 检测指标 ID + * + * 关联 {@link MesQcIndicatorDO#getId()} + */ + private Long indicatorId; + /** + * 检测工具 + * + * 冗余 {@link MesQcIndicatorDO#getTool()} + */ + private String tool; + /** + * 检测方法 + */ + private String checkMethod; + /** + * 标准值 + */ + private BigDecimal standardValue; + /** + * 计量单位 ID + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long unitMeasureId; + /** + * 误差上限 + */ + private BigDecimal maxThreshold; + /** + * 误差下限 + */ + private BigDecimal minThreshold; + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java new file mode 100644 index 000000000..ce7a97eed --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java @@ -0,0 +1,186 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 出货检验单(OQC, Outgoing Quality Control) DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_oqc") +@KeySequence("mes_qc_oqc_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcOqcDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 检验单编号 + */ + private String code; + /** + * 检验单名称 + */ + private String name; + /** + * 检验模板 ID + * + * 关联 {@link MesQcTemplateDO#getId()} + */ + private Long templateId; + + // ========== 来源单据 ========== + + /** + * 来源单据 ID + * + * 关联:根据 {@link #sourceDocType} 不同: + * 1. {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum#PRODUCT_SALES} 时,关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO#getId()} + */ + private Long sourceDocId; + /** + * 来源单据类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum} + */ + private Integer sourceDocType; + /** + * 来源单据行 ID + * + * 关联:根据 {@link #sourceDocType} 不同: + * 1. {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum#PRODUCT_SALES} 时,关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO#getId()} + */ + private Long sourceLineId; + /** + * 来源单据编号(冗余) + */ + private String sourceDocCode; + + // ========== 客户 ========== + + /** + * 客户 ID + * + * 关联 {@link MesMdClientDO#getId()} + */ + private Long clientId; + /** + * 批次号 + */ + private String batchCode; + + // ========== 物料 ========== + + /** + * 产品物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + + // ========== 数量 ========== + + /** + * 最低检测数 + */ + private Integer minCheckQuantity; + /** + * 最大不合格数 + */ + private Integer maxUnqualifiedQuantity; + /** + * 本次出货数量 + */ + private BigDecimal outQuantity; + /** + * 本次检测数量 + */ + private BigDecimal checkQuantity; + /** + * 合格品数量 + */ + private BigDecimal qualifiedQuantity; + /** + * 不合格品数量 + */ + private BigDecimal unqualifiedQuantity; + + // ========== 缺陷统计 ========== + + /** + * 致命缺陷率(%) + */ + private BigDecimal criticalRate; + /** + * 严重缺陷率(%) + */ + private BigDecimal majorRate; + /** + * 轻微缺陷率(%) + */ + private BigDecimal minorRate; + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + + // ========== 检验 ========== + + /** + * 检测结果 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum} + */ + private Integer checkResult; + /** + * 出货日期 + */ + private LocalDateTime outDate; + /** + * 检测日期 + */ + private LocalDateTime inspectDate; + /** + * 检测人员用户 ID + * + * 关联 AdminUserDO 的 id + */ + private Long inspectorUserId; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcLineDO.java new file mode 100644 index 000000000..3d973c97f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcLineDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 出货检验单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_oqc_line") +@KeySequence("mes_qc_oqc_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcOqcLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 出货检验单 ID + * + * 关联 {@link MesQcOqcDO#getId()} + */ + private Long oqcId; + /** + * 检测指标 ID + * + * 关联 {@link MesQcIndicatorDO#getId()} + */ + private Long indicatorId; + /** + * 检测工具 + * + * 冗余 {@link MesQcIndicatorDO#getTool()} + */ + private String tool; + /** + * 检测方法 + */ + private String checkMethod; + /** + * 标准值 + */ + private BigDecimal standardValue; + /** + * 计量单位 ID + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long unitMeasureId; + /** + * 误差上限 + */ + private BigDecimal maxThreshold; + /** + * 误差下限 + */ + private BigDecimal minThreshold; + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java new file mode 100644 index 000000000..868f4c91c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java @@ -0,0 +1,164 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 退货检验单(RQC, Return Quality Control) DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_rqc") +@KeySequence("mes_qc_rqc_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcRqcDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 检验单编号 + */ + private String code; + /** + * 检验单名称 + */ + private String name; + /** + * 检验模板 ID + * + * 关联 {@link MesQcTemplateDO#getId()} + */ + private Long templateId; + + // ========== 来源单据 ========== + + /** + * 来源单据 ID + */ + private Long sourceDocId; + /** + * 来源单据类型 + * + * 关联 {@link cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants} + */ + private Integer sourceDocType; + /** + * 来源单据行 ID + */ + private Long sourceLineId; + /** + * 来源单据编码(冗余) + */ + private String sourceDocCode; + + // ========== 检验类型 ========== + + /** + * 检验类型 + * + * 字典 mes_rqc_type + */ + private Integer type; + + // ========== 物料 ========== + + /** + * 产品物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 批次号 + */ + private String batchCode; + + // ========== 数量 ========== + + /** + * 检测数量 + */ + private BigDecimal checkQuantity; + /** + * 合格品数量 + */ + private BigDecimal qualifiedQuantity; + /** + * 不合格数量 + */ + private BigDecimal unqualifiedQuantity; + + // ========== 检验 ========== + + /** + * 检测结果 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum} + */ + private Integer checkResult; + /** + * 检测日期 + */ + private LocalDateTime inspectDate; + /** + * 检测人员用户 ID + * + * 关联 AdminUserDO 的 id + */ + private Long inspectorUserId; + /** + * 状态 + * + * 枚举 {@link MesQcStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + + // ========== 缺陷统计 ========== + + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + /** + * 致命缺陷率(%) + */ + private BigDecimal criticalRate; + /** + * 严重缺陷率(%) + */ + private BigDecimal majorRate; + /** + * 轻微缺陷率(%) + */ + private BigDecimal minorRate; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcLineDO.java new file mode 100644 index 000000000..44c7c694c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcLineDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 退货检验行 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_rqc_line") +@KeySequence("mes_qc_rqc_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcRqcLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退货检验单 ID + * + * 关联 {@link MesQcRqcDO#getId()} + */ + private Long rqcId; + /** + * 检测指标 ID + * + * 关联 {@link MesQcIndicatorDO#getId()} + */ + private Long indicatorId; + /** + * 检测工具 + * + * 冗余 {@link MesQcIndicatorDO#getTool()} + */ + private String tool; + /** + * 检测方法 + */ + private String checkMethod; + /** + * 标准值 + */ + private BigDecimal standardValue; + /** + * 计量单位 ID + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long unitMeasureId; + /** + * 误差上限 + */ + private BigDecimal maxThreshold; + /** + * 误差下限 + */ + private BigDecimal minThreshold; + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateDO.java new file mode 100644 index 000000000..72aa254d5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateDO.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.template; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.util.List; + +/** + * MES 质检方案 DO + * + * @author 芋道源码 + */ +@TableName(value = "mes_qc_template", autoResultMap = true) +@KeySequence("mes_qc_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcTemplateDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 方案编号 + */ + private String code; + /** + * 方案名称 + */ + private String name; + /** + * 检测种类 + * + * 字典 {@link DictTypeConstants#MES_QC_TYPE} + */ + @TableField(typeHandler = IntegerListTypeHandler.class) + private List types; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateIndicatorDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateIndicatorDO.java new file mode 100644 index 000000000..82b8abcfb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateIndicatorDO.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.template; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 质检方案-检测指标项 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_template_indicator") +@KeySequence("mes_qc_template_indicator_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcTemplateIndicatorDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 质检方案编号 + * + * 关联 {@link MesQcTemplateDO#getId()} + */ + private Long templateId; + /** + * 质检指标编号 + * + * 关联 {@link MesQcIndicatorDO#getId()} + */ + private Long indicatorId; + /** + * 检测方法 + */ + private String checkMethod; + /** + * 标准值 + */ + private BigDecimal standardValue; + /** + * 计量单位编号 + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long unitMeasureId; + /** + * 误差上限 + */ + private BigDecimal thresholdMax; + /** + * 误差下限 + */ + private BigDecimal thresholdMin; + /** + * 说明图 URL + */ + private String docUrl; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateItemDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateItemDO.java new file mode 100644 index 000000000..01476d5ee --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/template/MesQcTemplateItemDO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.template; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 质检方案-产品关联 DO + * + * @author 芋道源码 + */ +@TableName("mes_qc_template_item") +@KeySequence("mes_qc_template_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesQcTemplateItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 质检方案编号 + * + * 关联 {@link MesQcTemplateDO#getId()} + */ + private Long templateId; + /** + * 产品物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 最低检测数 + */ + private Integer quantityCheck; + /** + * 最大不合格数(0=不启用) + */ + private Integer quantityUnqualified; + /** + * 最大致命缺陷率(%,0=不允许) + */ + private BigDecimal criticalRate; + /** + * 最大严重缺陷率(%,0=不允许) + */ + private BigDecimal majorRate; + /** + * 最大轻微缺陷率(%) + */ + private BigDecimal minorRate; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolDO.java new file mode 100644 index 000000000..b48a74277 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolDO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.tm.MesTmToolStatusEnum; +import cn.iocoder.yudao.module.mes.enums.tm.MesTmMaintenTypeEnum; +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_tm_tool") +@KeySequence("mes_tm_tool_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesTmToolDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 工具编码 + */ + private String code; + /** + * 工具名称 + */ + private String name; + /** + * 品牌 + */ + private String brand; + /** + * 型号规格 + */ + private String spec; + /** + * 工具类型编号 + * + * 关联 {@link MesTmToolTypeDO#getId()} + */ + private Long toolTypeId; + /** + * 数量 + */ + private Integer quantity; + /** + * 可用数量 + */ + private Integer availableQuantity; + /** + * 保养维护类型 + * + * 枚举 {@link MesTmMaintenTypeEnum} + */ + private Integer maintenType; + /** + * 下次保养周期(次数) + */ + private Integer nextMaintenPeriod; + /** + * 下次保养日期 + */ + private LocalDateTime nextMaintenDate; + /** + * 状态 + * + * 枚举 {@link MesTmToolStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolTypeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolTypeDO.java new file mode 100644 index 000000000..c261ba8f3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolTypeDO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.tm.MesTmMaintenTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 工具类型 DO + * + * @author 芋道源码 + */ +@TableName("mes_tm_tool_type") +@KeySequence("mes_tm_tool_type_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesTmToolTypeDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 类型编码 + */ + private String code; + /** + * 类型名称 + */ + private String name; + /** + * 是否编码管理 + */ + private Boolean codeFlag; + /** + * 保养维护类型 + * + * 枚举 {@link MesTmMaintenTypeEnum} + */ + private Integer maintenType; + /** + * 保养周期 + */ + private Integer maintenPeriod; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java new file mode 100644 index 000000000..41e232c56 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; +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 + */ +@TableName("mes_wm_arrival_notice") +@KeySequence("mes_wm_arrival_notice_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmArrivalNoticeDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 通知单编码 + */ + private String code; + /** + * 通知单名称 + */ + private String name; + /** + * 采购订单编号 + */ + private String purchaseOrderCode; + /** + * 供应商编号 + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 到货日期 + */ + private LocalDateTime arrivalDate; + /** + * 联系人 + */ + private String contactName; + /** + * 联系电话 + */ + private String contactTelephone; + /** + * 状态 + * + * 枚举 {@link MesWmArrivalNoticeStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeLineDO.java new file mode 100644 index 000000000..e3c14f6c3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeLineDO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 到货通知单行 DO + */ +@TableName("mes_wm_arrival_notice_line") +@KeySequence("mes_wm_arrival_notice_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmArrivalNoticeLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 到货通知单编号 + * + * 关联 {@link MesWmArrivalNoticeDO#getId()} + */ + private Long noticeId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 到货数量 + */ + private BigDecimal arrivalQuantity; + /** + * 合格数量 + */ + private BigDecimal qualifiedQuantity; + /** + * 是否需要来料检验 + */ + private Boolean iqcCheckFlag; + /** + * 来料检验单编号 + * + * 关联 {@link MesQcIqcDO#getId()} + */ + private Long iqcId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeConfigDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeConfigDO.java new file mode 100644 index 000000000..0d44f133a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeConfigDO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode; + +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.*; + +/** + * MES 条码配置 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_barcode_config") +@KeySequence("mes_wm_barcode_config_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmBarcodeConfigDO extends BaseDO { + + /** + * 内容格式模板占位符 + */ + public static final String PLACEHOLDER_BUSINESS_CODE = "{BUSINESSCODE}"; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 条码格式 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.BarcodeFormatEnum} + */ + private Integer format; + /** + * 业务类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum} + */ + private Integer bizType; + /** + * 内容格式模板(支持 {BUSINESSCODE} 占位符) + * + * @see #PLACEHOLDER_BUSINESS_CODE + */ + private String contentFormat; + /** + * 内容样例 + */ + private String contentExample; + /** + * 是否自动生成 + */ + private Boolean autoGenerateFlag; + /** + * 默认打印模板 + */ + private String defaultTemplate; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeDO.java new file mode 100644 index 000000000..2205bb9bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeDO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode; + +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.*; + +/** + * MES 条码清单 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_barcode") +@KeySequence("mes_wm_barcode_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmBarcodeDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 条码配置编号 + * + * 关联 {@link MesWmBarcodeConfigDO#getId()} + */ + private Long configId; + /** + * 条码格式 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.BarcodeFormatEnum} + */ + private Integer format; + /** + * 业务类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum} + */ + private Integer bizType; + /** + * 条码内容(核心字段,前端根据此内容生成条码图片) + */ + private String content; + /** + * 业务编号 + */ + private Long bizId; + /** + * 业务编码 + */ + private String bizCode; + /** + * 业务名称 + */ + private String bizName; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java new file mode 100644 index 000000000..261759604 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/batch/MesWmBatchDO.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +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.tm.tool.MesTmToolDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 批次管理 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_batch") +@KeySequence("mes_wm_batch_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmBatchDO extends BaseDO { + + /** + * 批次ID + */ + @TableId + private Long id; + /** + * 批次编码 + */ + private String code; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 生产日期 + */ + private LocalDateTime produceDate; + /** + * 有效期 + */ + private LocalDateTime expireDate; + /** + * 入库日期 + */ + private LocalDateTime receiptDate; + /** + * 供应商ID + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 客户ID + * + * 关联 {@link MesMdClientDO#getId()} + */ + private Long clientId; + + /** + * 销售订单编号 + */ + private String salesOrderCode; + /** + * 采购订单编号 + */ + private String purchaseOrderCode; + /** + * 生产工单ID + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 生产任务ID + * + * 关联 {@link MesProTaskDO#getId()} + */ + private Long taskId; + /** + * 工作站ID + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 工具ID + * + * 关联 {@link MesTmToolDO#getId()} + */ + private Long toolId; + /** + * 模具 ID + */ + private Long moldId; + /** + * 生产批号 + */ + private String lotNumber; + /** + * 质量状态 + */ + private Integer qualityStatus; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDO.java new file mode 100644 index 000000000..577cf8d4a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +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 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_wm_item_consume") +@KeySequence("mes_wm_item_consume_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmItemConsumeDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 生产任务编号 + * + * 关联 {@link MesProTaskDO#getId()} + */ + private Long taskId; + /** + * 工作站编号 + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 工序编号 + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 报工记录编号 + * + * 关联 {@link MesProFeedbackDO#getId()} + */ + private Long feedbackId; + /** + * 消耗日期 + */ + private LocalDateTime consumeDate; + // DONE @AI:搞个独立的枚举类; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmItemConsumeStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDetailDO.java new file mode 100644 index 000000000..daae8fb4f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDetailDO.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 物料消耗记录明细 DO + * + * 记录 line 级别的消耗按线边库 FIFO 分配到具体批次的明细。 + * 一条 line 可能拆分为多条 detail(当一个批次库存不够,需要从下一个批次继续分配时)。 + * + * @author 芋道源码 + */ +@TableName("mes_wm_item_consume_detail") +@KeySequence("mes_wm_item_consume_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmItemConsumeDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 消耗记录编号 + * + * 关联 {@link MesWmItemConsumeDO#getId()} + */ + private Long consumeId; + /** + * 消耗记录行编号 + * + * 关联 {@link MesWmItemConsumeLineDO#getId()} + */ + private Long lineId; + /** + * 库存台账编号 + * + * 关联 {@link MesWmMaterialStockDO#getId()} + * 当线边库中无可用库存时为 null + */ + private Long materialStockId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 消耗数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 冗余 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeLineDO.java new file mode 100644 index 000000000..635787ba0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeLineDO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 物料消耗记录行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_item_consume_line") +@KeySequence("mes_wm_item_consume_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmItemConsumeLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 消耗记录编号 + * + * 关联 {@link MesWmItemConsumeDO#getId()} + */ + private Long consumeId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 消耗数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 冗余 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java new file mode 100644 index 000000000..1dea8d232 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum; +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 + */ +@TableName("mes_wm_item_receipt") +@KeySequence("mes_wm_item_receipt_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmItemReceiptDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单编码 + */ + private String code; + /** + * 入库单名称 + */ + private String name; + /** + * 来料检验单编号 + * + * 关联 {@link MesQcIqcDO#getId()} + */ + private Long iqcId; + /** + * 到货通知单编号 + * + * 关联 {@link MesWmArrivalNoticeDO#getId()} + */ + private Long noticeId; + /** + * 采购订单号 + * + * 冗余自 {@link MesWmArrivalNoticeDO#getPurchaseOrderCode()},也可以手动填写 + */ + private String purchaseOrderCode; + /** + * 供应商编号 + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 入库日期 + */ + private LocalDateTime receiptDate; + /** + * 状态 + * + * 枚举 {@link MesWmItemReceiptStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDetailDO.java new file mode 100644 index 000000000..3b37851df --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDetailDO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 采购入库明细 DO + */ +@TableName("mes_wm_item_receipt_detail") +@KeySequence("mes_wm_item_receipt_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmItemReceiptDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单行编号 + * + * 关联 {@link MesWmItemReceiptLineDO#getId()} + */ + private Long lineId; + /** + * 入库单编号 + * + * 关联 {@link MesWmItemReceiptDO#getId()} + */ + private Long receiptId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 上架数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + * + * TODO DONE @芋艿:保留。待 mes_wm_batch 模块迁移后补充 @link 关联 + */ + private Long batchId; + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptLineDO.java new file mode 100644 index 000000000..3c3f65d2b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptLineDO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 采购入库单行 DO + */ +@TableName("mes_wm_item_receipt_line") +@KeySequence("mes_wm_item_receipt_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmItemReceiptLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单编号 + * + * 关联 {@link MesWmItemReceiptDO#getId()} + */ + private Long receiptId; + /** + * 到货通知单行编号 + * + * 关联 {@link MesWmArrivalNoticeLineDO#getId()} + */ + private Long arrivalNoticeLineId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 入库数量 + */ + private BigDecimal receivedQuantity; + /** + * 批次编号 + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次编码 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 生产日期 + */ + private LocalDateTime productionDate; + /** + * 有效期 + */ + private LocalDateTime expireDate; + /** + * 生产批号 + */ + private String lotNumber; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java new file mode 100644 index 000000000..502884144 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 库存台账(仓库现有量)DO + */ +@TableName("mes_wm_material_stock") +@KeySequence("mes_wm_material_stock_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmMaterialStockDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + + /** + * 在库数量 + */ + private BigDecimal quantity; + /** + * 入库时间 + */ + private LocalDateTime receiptTime; + + /** + * 供应商编号 + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + + // ==================== 物料维度 ==================== + + /** + * 物料分类编号 + * + * 关联 {@link MesMdItemTypeDO#getId()} + */ + private Long itemTypeId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 批次编号 + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + + // ==================== 库存位置 ==================== + + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + + // ==================== 状态 ==================== + + /** + * 是否冻结 + */ + private Boolean frozen; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDO.java new file mode 100644 index 000000000..cd722a04a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscIssueStatusEnum; +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 + */ +@TableName("mes_wm_misc_issue") +@KeySequence("mes_wm_misc_issue_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmMiscIssueDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 出库单编号 + */ + private String code; + /** + * 出库单名称 + */ + private String name; + /** + * 杂项类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscIssueTypeEnum} + */ + private Integer type; + // TODO @芋艿:这里还没定,关联哪些; + /** + * 来源单据ID + */ + private Long sourceDocId; + /** + * 来源单据编号 + */ + private String sourceDocCode; + /** + * 来源单据类型 + */ + private String sourceDocType; + /** + * 出库日期 + */ + private LocalDateTime issueDate; + /** + * 状态 + * + * 枚举 {@link MesWmMiscIssueStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDetailDO.java new file mode 100644 index 000000000..1126acdc7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDetailDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 杂项出库明细 DO + */ +@TableName("mes_wm_misc_issue_detail") +@KeySequence("mes_wm_misc_issue_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmMiscIssueDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 出库单ID + * + * 关联 {@link MesWmMiscIssueDO#getId()} + */ + private Long issueId; + /** + * 行ID + * + * 关联 {@link MesWmMiscIssueLineDO#getId()} + */ + private Long lineId; + /** + * 库存记录ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 出库数量 + */ + private BigDecimal quantity; + /** + * 批次ID + */ + private Long batchId; + /** + * 批次号 + */ + private String batchCode; + /** + * 仓库ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java new file mode 100644 index 000000000..9a05b50ca --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueLineDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 杂项出库单行 DO + */ +@TableName("mes_wm_misc_issue_line") +@KeySequence("mes_wm_misc_issue_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmMiscIssueLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 出库单编号 + * + * 关联 {@link MesWmMiscIssueDO#getId()} + */ + private Long issueId; + /** + * 来源单据行ID + */ + private Long sourceDocLineId; + /** + * 库存记录ID + */ + private Long materialStockId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 出库数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 挂你兰 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDO.java new file mode 100644 index 000000000..635ca292f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscReceiptStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscReceiptTypeEnum; +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_wm_misc_receipt") +@KeySequence("mes_wm_misc_receipt_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmMiscReceiptDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单编码 + */ + private String code; + /** + * 入库单名称 + */ + private String name; + /** + * 杂项类型 + * + * 枚举 {@link MesWmMiscReceiptTypeEnum} + */ + private Integer type; + /** + * 来源单据 ID + */ + private Long sourceDocId; + /** + * 来源单据编码 + */ + private String sourceDocCode; + /** + * 来源单据类型 + */ + private String sourceDocType; + /** + * 入库日期 + */ + private LocalDateTime receiptDate; + /** + * 状态 + * + * 枚举 {@link MesWmMiscReceiptStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDetailDO.java new file mode 100644 index 000000000..44d79261d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDetailDO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 杂项入库明细 DO + */ +@TableName("mes_wm_misc_receipt_detail") +@KeySequence("mes_wm_misc_receipt_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmMiscReceiptDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单ID + * + * 关联 {@link MesWmMiscReceiptDO#getId()} + */ + private Long receiptId; + /** + * 行ID + * + * 关联 {@link MesWmMiscReceiptLineDO#getId()} + */ + private Long lineId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 入库数量 + */ + private BigDecimal quantity; + /** + * 批次号 + */ + private String batchCode; + /** + * 仓库ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptLineDO.java new file mode 100644 index 000000000..0ea671700 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptLineDO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 杂项入库单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_misc_receipt_line") +@KeySequence("mes_wm_misc_receipt_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmMiscReceiptLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单编号 + * + * 关联 {@link MesWmMiscReceiptDO#getId()} + */ + private Long receiptId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 入库数量 + */ + private BigDecimal quantity; + /** + * 批次号 + */ + private String batchCode; + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java new file mode 100644 index 000000000..a74915721 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceIssueStatusEnum; +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_wm_outsource_issue") +@KeySequence("mes_wm_outsource_issue_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceIssueDO extends BaseDO { + + /** + * 发料单ID + */ + @TableId + private Long id; + /** + * 发料单编号 + */ + private String code; + /** + * 发料单名称 + */ + private String name; + /** + * 供应商ID + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 生产工单ID + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 发料日期 + */ + private LocalDateTime issueDate; + /** + * 单据状态 + * + * 枚举 {@link MesWmOutsourceIssueStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDetailDO.java new file mode 100644 index 000000000..d8c64ae55 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDetailDO.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 外协发料单明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_outsource_issue_detail") +@KeySequence("mes_wm_outsource_issue_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceIssueDetailDO extends BaseDO { + + /** + * 明细ID + */ + @TableId + private Long id; + /** + * 行ID + * + * 关联 {@link MesWmOutsourceIssueLineDO#getId()} + */ + private Long lineId; + /** + * 发料单ID + * + * 关联 {@link MesWmOutsourceIssueDO#getId()} + */ + private Long issueId; + /** + * 库存ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 数量 + */ + private BigDecimal quantity; + /** + * 批次ID + */ + private Long batchId; + /** + * 仓库ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库位ID + */ + private Long locationId; + /** + * 库区ID + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java new file mode 100644 index 000000000..b8717b750 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueLineDO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 外协发料单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_outsource_issue_line") +@KeySequence("mes_wm_outsource_issue_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceIssueLineDO extends BaseDO { + + /** + * 行ID + */ + @TableId + private Long id; + /** + * 发料单ID + * + * 关联 {@link MesWmOutsourceIssueDO#getId()} + */ + private Long issueId; + /** + * 库存ID + */ + private Long materialStockId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 发料数量 + */ + private BigDecimal quantity; + /** + * 批次ID + */ + private Long batchId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java new file mode 100644 index 000000000..589721fb8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceReceiptStatusEnum; +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 + */ +@TableName("mes_wm_outsource_receipt") +@KeySequence("mes_wm_outsource_receipt_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceReceiptDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单编码 + */ + private String code; + /** + * 入库单名称 + */ + private String name; + /** + * 外协工单编号 + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 供应商编号 + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 入库日期 + */ + private LocalDateTime receiptDate; + /** + * 状态 + * + * 枚举 {@link MesWmOutsourceReceiptStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDetailDO.java new file mode 100644 index 000000000..667044bc3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDetailDO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 外协入库明细 DO + */ +@TableName("mes_wm_outsource_receipt_detail") +@KeySequence("mes_wm_outsource_receipt_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceReceiptDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单行编号 + * + * 关联 {@link MesWmOutsourceReceiptLineDO#getId()} + */ + private Long lineId; + /** + * 入库单编号 + * + * 关联 {@link MesWmOutsourceReceiptDO#getId()} + */ + private Long receiptId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 上架数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + * + * DONE @芋艿:保留。待 mes_wm_batch 模块迁移后补充 @link 关联(AI 未修复原因:标注为后续处理,需人工介入) + */ + private Long batchId; + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptLineDO.java new file mode 100644 index 000000000..30dd611c0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptLineDO.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 外协入库单行 DO + */ +@TableName("mes_wm_outsource_receipt_line") +@KeySequence("mes_wm_outsource_receipt_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmOutsourceReceiptLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单编号 + * + * 关联 {@link MesWmOutsourceReceiptDO#getId()} + */ + private Long receiptId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 入库数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 生产日期 + */ + private LocalDateTime productionDate; + /** + * 有效期 + */ + private LocalDateTime expireDate; + /** + * 生产批号 + */ + private String lotNumber; + /** + * 备注 + */ + private String remark; + /** + * 来料检验单编号 + * + * 关联 {@link MesQcIqcDO#getId()} + */ + private Long iqcId; + /** + * 是否需要质检 + */ + private Boolean iqcCheckFlag; + /** + * 质量状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} + */ + private Integer qualityStatus; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java new file mode 100644 index 000000000..bef8c8207 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 装箱单 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_package") +@KeySequence("mes_wm_package_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmPackageDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + @TableId + private Long id; + /** + * 装箱单编号 + */ + private String code; + /** + * 父箱 ID + */ + private Long parentId; + /** + * 装箱日期 + */ + private LocalDateTime packageDate; + /** + * 销售订单编号 + */ + private String salesOrderCode; + /** + * 发票编号 + */ + private String invoiceCode; + /** + * 客户 ID + * + * 关联 {@link MesMdClientDO#getId()} + */ + private Long clientId; + /** + * 箱长度 + */ + private BigDecimal length; + /** + * 箱宽度 + */ + private BigDecimal width; + /** + * 箱高度 + */ + private BigDecimal height; + /** + * 尺寸单位 ID + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long sizeUnitId; + /** + * 净重 + */ + private BigDecimal netWeight; + /** + * 毛重 + */ + private BigDecimal grossWeight; + /** + * 重量单位 ID + * + * 关联 {@link MesMdUnitMeasureDO#getId()} + */ + private Long weightUnitId; + /** + * 检查员用户 ID + * + * 关联 AdminUserDO 的 id + */ + private Long inspectorUserId; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmPackageStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageLineDO.java new file mode 100644 index 000000000..8ffdbbfbd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageLineDO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 装箱明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_package_line") +@KeySequence("mes_wm_package_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmPackageLineDO extends BaseDO { + + @TableId + private Long id; + /** + * 装箱单 ID + * + * 关联 {@link MesWmPackageDO#getId()} + */ + private Long packageId; + /** + * 库存记录 ID + */ + private Long materialStockId; + /** + * 产品物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 装箱数量 + */ + private BigDecimal quantity; + // DONE @芋艿:需要在确认下; + /** + * 生产工单 ID + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 有效期 + */ + private LocalDateTime expireDate; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDO.java new file mode 100644 index 000000000..83f414c6e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +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.enums.wm.MesWmProductIssueStatusEnum; +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 + */ +@TableName("mes_wm_product_issue") +@KeySequence("mes_wm_product_issue_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductIssueDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 领料单编号 + */ + private String code; + /** + * 领料单名称 + */ + private String name; + /** + * 工作站 ID + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 生产工单 ID + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + // TODO @芋艿:【疑问,不要动】这个字段的来源? + /** + * 生产任务 ID + * + * 关联 {@link MesProTaskDO#getId()} + */ + private Long taskId; + // TODO @芋艿:【疑问,不要动】这个字段的更新时间; + /** + * 领料日期 + */ + private LocalDateTime issueDate; + /** + * 需求时间 + */ + private LocalDateTime requiredTime; + /** + * 状态 + * + * 枚举 {@link MesWmProductIssueStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDetailDO.java new file mode 100644 index 000000000..6690dbf0c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDetailDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 领料出库明细 DO + */ +@TableName("mes_wm_product_issue_detail") +@KeySequence("mes_wm_product_issue_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductIssueDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 领料单ID + * + * 关联 {@link MesWmProductIssueDO#getId()} + */ + private Long issueId; + /** + * 行ID + * + * 关联 {@link MesWmProductIssueLineDO#getId()} + */ + private Long lineId; + /** + * 库存记录ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 领料数量 + */ + private BigDecimal quantity; + /** + * 批次ID + */ + private Long batchId; + /** + * 批次号 + */ + private String batchCode; + /** + * 仓库ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueLineDO.java new file mode 100644 index 000000000..89d8d6a99 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueLineDO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 领料出库单行 DO + */ +@TableName("mes_wm_product_issue_line") +@KeySequence("mes_wm_product_issue_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductIssueLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 领料单 ID + * + * 关联 {@link MesWmProductIssueDO#getId()} + */ + private Long issueId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 领料数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + */ + private Long batchId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDO.java new file mode 100644 index 000000000..4d29666c9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +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.enums.wm.MesWmProductProduceStatusEnum; +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_wm_product_produce") +@KeySequence("mes_wm_product_produce_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductProduceDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 生产工单 ID + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 报工记录 ID + * + * 关联 {@link MesProFeedbackDO#getId()} + */ + private Long feedbackId; + /** + * 生产任务 ID + * + * 关联 {@link MesProTaskDO#getId()} + */ + private Long taskId; + /** + * 工作站 ID + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 工序 ID + * + * 关联 {@link MesProProcessDO#getId()} + */ + private Long processId; + /** + * 生产日期 + */ + private LocalDateTime produceDate; + /** + * 状态 + * + * 枚举 {@link MesWmProductProduceStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDetailDO.java new file mode 100644 index 000000000..d24290732 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDetailDO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 生产入库明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_product_produce_detail") +@KeySequence("mes_wm_product_produce_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductProduceDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单 ID + * + * 关联 {@link MesWmProductProduceDO#getId()} + */ + private Long produceId; + /** + * 行 ID + * + * 关联 {@link MesWmProductProduceLineDO#getId()} + */ + private Long lineId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 入库数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + */ + private Long batchId; + /** + * 批次号 + */ + private String batchCode; + /** + * 仓库 ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区 ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位 ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceLineDO.java new file mode 100644 index 000000000..fb2733eca --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceLineDO.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 生产入库单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_product_produce_line") +@KeySequence("mes_wm_product_produce_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductProduceLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 入库单 ID + * + * 关联 {@link MesWmProductProduceDO#getId()} + */ + private Long produceId; + /** + * 报工记录 ID + * + * 关联 {@link MesProFeedbackDO#getId()} + */ + private Long feedbackId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 入库数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + */ + private Long batchId; + /** + * 批次号 + */ + private String batchCode; + /** + * 过期日期 + */ + private LocalDateTime expireDate; + /** + * 生产批号 + */ + private String lotNumber; + /** + * 质量状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} + */ + private Integer qualityStatus; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDO.java new file mode 100644 index 000000000..df832998f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductReceiptStatusEnum; +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 + */ +@TableName("mes_wm_product_receipt") +@KeySequence("mes_wm_product_receipt_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductReceiptDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 收货单编码 + */ + private String code; + /** + * 收货单名称 + */ + private String name; + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 产品物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 收货日期 + */ + private LocalDateTime receiptDate; + /** + * 状态 + * + * 枚举 {@link MesWmProductReceiptStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDetailDO.java new file mode 100644 index 000000000..91c1c8728 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDetailDO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 产品收货(入库)单明细 DO + */ +@TableName("mes_wm_product_receipt_detail") +@KeySequence("mes_wm_product_receipt_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductReceiptDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 收货单行编号 + * + * 关联 {@link MesWmProductReceiptLineDO#getId()} + */ + private Long lineId; + /** + * 收货单编号 + * + * 关联 {@link MesWmProductReceiptDO#getId()} + */ + private Long receiptId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 上架数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + * + * TODO DONE @芋艿:保留。待 mes_wm_batch 模块迁移后补充 @link 关联 + */ + private Long batchId; + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptLineDO.java new file mode 100644 index 000000000..bf0d3780c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptLineDO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 产品收货(入库)单行 DO + */ +@TableName("mes_wm_product_receipt_line") +@KeySequence("mes_wm_product_receipt_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductReceiptLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 收货单编号 + * + * 关联 {@link MesWmProductReceiptDO#getId()} + */ + private Long receiptId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 库存物资记录编号 + * + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 收货数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java new file mode 100644 index 000000000..c86fb3a3d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; +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_wm_product_sales") +@KeySequence("mes_wm_product_sales_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductSalesDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 出库单号 + */ + private String code; + /** + * 出库单名称 + */ + private String name; + /** + * 客户ID + * + * 关联 {@link MesMdClientDO#getId()} + */ + private Long clientId; + /** + * 销售订单号 + */ + private String salesOrderCode; + /** + * 出库日期 + */ + private LocalDateTime salesDate; + + /** + * 发货通知单 ID + * + * 关联 {@link MesWmSalesNoticeDO#getId()} + */ + private Long noticeId; + + /** + * 联系人 + */ + private String contactName; + /** + * 联系电话 + */ + private String contactTelephone; + /** + * 收货地址 + */ + private String contactAddress; + + /** + * 承运商 + */ + private String carrier; + /** + * 运输单号 + */ + private String shippingNumber; + + /** + * 状态 + * + * 枚举 {@link MesWmProductSalesStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDetailDO.java new file mode 100644 index 000000000..865b8d927 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDetailDO.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 销售出库明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_product_sales_detail") +@KeySequence("mes_wm_product_sales_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductSalesDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 出库单行ID + * + * 关联 {@link MesWmProductSalesLineDO#getId()} + */ + private Long lineId; + /** + * 出库单ID + * + * 关联 {@link MesWmProductSalesDO#getId()} + */ + private Long salesId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 拣货数量 + */ + private BigDecimal quantity; + /** + * 库存记录ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 批次 ID + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 仓库ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java new file mode 100644 index 000000000..cf390f754 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java @@ -0,0 +1,91 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 销售出库单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_product_sales_line") +@KeySequence("mes_wm_product_sales_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmProductSalesLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 出库单ID + * + * 关联 {@link MesWmProductSalesDO#getId()} + */ + private Long salesId; + /** + * 物料ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 出库数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 库存记录ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 是否出厂检验 + */ + private Boolean oqcCheckFlag; + /** + * 出厂检验单 ID + * + * 关联 {@link MesQcOqcDO#getId()} + */ + private Long oqcId; + /** + * 质量状态 + * + * 枚举 {@link MesWmQualityStatusEnum} + */ + private Integer qualityStatus; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDO.java new file mode 100644 index 000000000..d0acb3700 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueStatusEnum; +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 + */ +@TableName("mes_wm_return_issue") +@KeySequence("mes_wm_return_issue_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnIssueDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退料单编号 + */ + private String code; + /** + * 退料单名称 + */ + private String name; + /** + * 生产工单 ID + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + /** + * 工作站 ID + * + * 关联 {@link MesMdWorkstationDO#getId()} + */ + private Long workstationId; + /** + * 退料类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueTypeEnum} + */ + private Integer type; + /** + * 退料日期 + */ + private LocalDateTime returnDate; + /** + * 状态 + * + * 枚举 {@link MesWmReturnIssueStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDetailDO.java new file mode 100644 index 000000000..64fd54ec4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDetailDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 生产退料明细 DO + */ +@TableName("mes_wm_return_issue_detail") +@KeySequence("mes_wm_return_issue_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnIssueDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退料单 ID + * + * 关联 {@link MesWmReturnIssueDO#getId()} + */ + private Long issueId; + /** + * 行 ID + * + * 关联 {@link MesWmReturnIssueLineDO#getId()} + */ + private Long lineId; + /** + * 库存记录 ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 退料数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + */ + private Long batchId; + /** + * 批次号 + */ + private String batchCode; + /** + * 仓库 ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区 ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位 ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueLineDO.java new file mode 100644 index 000000000..00b3ca16b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueLineDO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 生产退料单行 DO + */ +@TableName("mes_wm_return_issue_line") +@KeySequence("mes_wm_return_issue_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnIssueLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退料单 ID + * + * 关联 {@link MesWmReturnIssueDO#getId()} + */ + private Long issueId; + /** + * 库存记录 ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 退料数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次编码 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 退货检验单 ID + * + * 关联 {@link MesQcRqcDO#getId()} + */ + private Long rqcId; + /** + * 是否需要质检 + */ + private Boolean rqcCheckFlag; + /** + * 质量状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} + */ + private Integer qualityStatus; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDO.java new file mode 100644 index 000000000..bb4c0975a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; +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_wm_return_sales") +@KeySequence("mes_wm_return_sales_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnSalesDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退货单编号 + */ + private String code; + /** + * 退货单名称 + */ + private String name; + /** + * 销售订单编号 + */ + private String salesOrderCode; + /** + * 客户 ID + * + * 关联 {@link MesMdClientDO#getId()} + */ + private Long clientId; + /** + * 退货日期 + */ + private LocalDateTime returnDate; + /** + * 退货原因 + */ + private String returnReason; + /** + * 状态 + * + * 枚举 {@link MesWmReturnSalesStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDetailDO.java new file mode 100644 index 000000000..1a3fad65e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDetailDO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 销售退货明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_return_sales_detail") +@KeySequence("mes_wm_return_sales_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnSalesDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退货单 ID + * + * 关联 {@link MesWmReturnSalesDO#getId()} + */ + private Long returnId; + /** + * 行 ID + * + * 关联 {@link MesWmReturnSalesLineDO#getId()} + */ + private Long lineId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + */ + private Long batchId; + /** + * 仓库 ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区 ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位 ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java new file mode 100644 index 000000000..635409244 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 销售退货单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_return_sales_line") +@KeySequence("mes_wm_return_sales_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnSalesLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退货单 ID + * + * 关联 {@link MesWmReturnSalesDO#getId()} + */ + private Long returnId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 退货数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + */ + private Long batchId; + /** + * 退货检验单 ID + */ + private Long rqcId; + /** + * 是否需要质检 + */ + private Boolean rqcCheckFlag; + /** + * 质量状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} + */ + private Integer qualityStatus; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java new file mode 100644 index 000000000..1f307e375 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnVendorStatusEnum; +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 + */ +@TableName("mes_wm_return_vendor") +@KeySequence("mes_wm_return_vendor_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnVendorDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退货单编号 + */ + private String code; + /** + * 退货单名称 + */ + private String name; + /** + * 采购订单编号 + */ + private String purchaseOrderCode; + /** + * 供应商 ID + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 退货日期 + */ + private LocalDateTime returnDate; + /** + * 退货原因 + */ + private String returnReason; + /** + * 物流单号 + */ + private String transportCode; + /** + * 物流联系电话 + */ + private String transportTelephone; + /** + * 状态 + * + * 枚举 {@link MesWmReturnVendorStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDetailDO.java new file mode 100644 index 000000000..764321fa8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDetailDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 供应商退货明细 DO + */ +@TableName("mes_wm_return_vendor_detail") +@KeySequence("mes_wm_return_vendor_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnVendorDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退货单 ID + * + * 关联 {@link MesWmReturnVendorDO#getId()} + */ + private Long returnId; + /** + * 行 ID + * + * 关联 {@link MesWmReturnVendorLineDO#getId()} + */ + private Long lineId; + /** + * 库存记录 ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 退货数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + */ + private Long batchId; + /** + * 批次号 + */ + private String batchCode; + /** + * 仓库 ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区 ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位 ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorLineDO.java new file mode 100644 index 000000000..8ef63bfba --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorLineDO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 供应商退货单行 DO + */ +@TableName("mes_wm_return_vendor_line") +@KeySequence("mes_wm_return_vendor_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmReturnVendorLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 退货单 ID + * + * 关联 {@link MesWmReturnVendorDO#getId()} + */ + private Long returnId; + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 退货数量 + */ + private BigDecimal quantity; + /** + * 批次 ID + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java new file mode 100644 index 000000000..01a3ea7dd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +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 + */ +@TableName("mes_wm_sales_notice") +@KeySequence("mes_wm_sales_notice_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmSalesNoticeDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 通知单编码 + */ + private String noticeCode; + /** + * 通知单名称 + */ + private String noticeName; + /** + * 销售订单编号 + */ + private String salesOrderCode; + /** + * 客户编号 + * + * 关联 {@link MesMdClientDO#getId()} + */ + private Long clientId; + /** + * 发货日期 + */ + private LocalDateTime salesDate; + /** + * 收货人 + */ + private String recipientName; + /** + * 联系方式 + */ + private String recipientTelephone; + /** + * 收货地址 + */ + private String recipientAddress; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeLineDO.java new file mode 100644 index 000000000..7b033c139 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeLineDO.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 发货通知单行 DO + */ +@TableName("mes_wm_sales_notice_line") +@KeySequence("mes_wm_sales_notice_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmSalesNoticeLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 发货通知单编号 + * + * 关联 {@link MesWmSalesNoticeDO#getId()} + */ + private Long noticeId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 批次编号 + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + /** + * 发货数量 + */ + private BigDecimal quantity; + /** + * 是否检验 + */ + private Boolean oqcCheckFlag; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/sn/MesWmSnDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/sn/MesWmSnDO.java new file mode 100644 index 000000000..bb1fa981d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/sn/MesWmSnDO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.sn; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES SN 码 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_sn") +@KeySequence("mes_wm_sn_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmSnDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 批次 UUID(用于标记同一批次生成的 SN 码) + */ + private String uuid; + /** + * SN 码(唯一) + */ + private String code; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 批次号 + */ + private String batchCode; + // TODO @芋艿:【暂时不处理】看看后续要不要去掉这个字段。 + /** + * 生产工单编号 + * + * 关联 {@link MesProWorkOrderDO#getId()} + */ + private Long workOrderId; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanDO.java new file mode 100644 index 000000000..0f2a21915 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanDO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTypeEnum; +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_wm_stock_taking_plan") +@KeySequence("mes_wm_stock_taking_plan_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmStockTakingPlanDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + + /** + * 方案编码 + */ + private String code; + + /** + * 方案名称 + */ + private String name; + + /** + * 盘点类型 + * + * 枚举 {@link MesWmStockTakingTypeEnum} + */ + private Integer type; + /** + * 计划开始时间 + */ + private LocalDateTime startTime; + /** + * 计划结束时间 + */ + private LocalDateTime endTime; + + /** + * 是否盲盘 + */ + private Boolean blindFlag; + /** + * 是否冻结库存 + */ + private Boolean frozen; + + /** + * 状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanParamDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanParamDO.java new file mode 100644 index 000000000..e01edaa34 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanParamDO.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingPlanParamTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * MES 盘点方案参数 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_stock_taking_plan_param") +@KeySequence("mes_wm_stock_taking_plan_param_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmStockTakingPlanParamDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 盘点方案编号 + * + * 关联 {@link MesWmStockTakingPlanDO#getId()} + */ + private Long planId; + + /** + * 参数值类型 + * + * 枚举 {@link MesWmStockTakingPlanParamTypeEnum} + */ + private Integer type; + + /** + * 参数值编号,例如仓库、库区、库位、物料、批次的主键 ID + */ + private Long valueId; + /** + * 参数值编码,例如仓库编码、库区编码、库位编码、物料编码、批次编码 + */ + private String valueCode; + /** + * 参数值名称,例如仓库名称、库区名称、库位名称、物料名称、批次名称 + */ + private String valueName; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskDO.java new file mode 100644 index 000000000..7c42087ad --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskDO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTaskStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTypeEnum; +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_wm_stock_taking_task") +@KeySequence("mes_wm_stock_taking_task_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmStockTakingTaskDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 任务编码 + */ + private String code; + /** + * 任务名称 + */ + private String name; + /** + * 盘点日期 + */ + private LocalDateTime takingDate; + + /** + * 盘点类型 + * + * 枚举 {@link MesWmStockTakingTypeEnum} + */ + private Integer type; + /** + * 盘点人编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long userId; + + /** + * 盘点计划编号 + * + * 关联 {@link MesWmStockTakingPlanDO#getId()} + */ + private Long planId; + + /** + * 是否盲盘 + */ + private Boolean blindFlag; + /** + * 是否冻结库存 + */ + private Boolean frozen; + + /** + * 开始时间 + */ + private LocalDateTime startTime; + /** + * 结束时间 + */ + private LocalDateTime endTime; + + /** + * 任务状态 + * + * 枚举 {@link MesWmStockTakingTaskStatusEnum} + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskLineDO.java new file mode 100644 index 000000000..004ddfd92 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskLineDO.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTaskLineStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 盘点任务行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_stock_taking_task_line") +@KeySequence("mes_wm_stock_taking_task_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmStockTakingTaskLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 盘点任务编号 + * + * 关联 {@link MesWmStockTakingTaskDO#getId()} + */ + private Long taskId; + + /** + * 库存编号 + */ + private Long materialStockId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + + /** + * 批次编号 + */ + private Long batchId; + /** + * 批次编码 + */ + private String batchCode; + + /** + * 在库数量 + */ + private BigDecimal quantity; + /** + * 盘点数量 + */ + private BigDecimal takingQuantity; + + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} ()} + */ + private Long areaId; + + /** + * 盘点状态 + * + * 枚举 {@link MesWmStockTakingTaskLineStatusEnum} + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskResultDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskResultDO.java new file mode 100644 index 000000000..6d68d436c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskResultDO.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 盘点结果 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_stock_taking_task_result") +@KeySequence("mes_wm_stock_taking_task_result_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmStockTakingTaskResultDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 盘点任务编号 + * + * 关联 {@link MesWmStockTakingTaskDO#getId()} + */ + private Long taskId; + /** + * 盘点任务行编号 + * + * 关联 {@link MesWmStockTakingTaskLineDO#getId()} + */ + private Long lineId; + + /** + * 库存编号 + */ + private Long materialStockId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + + /** + * 批次编号 + */ + private Long batchId; + /** + * 批次编码 + */ + private String batchCode; + + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库位编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + + /** + * 在库数量 + */ + private BigDecimal quantity; + /** + * 盘点数量 + */ + private BigDecimal takingQuantity; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transaction/MesWmTransactionDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transaction/MesWmTransactionDO.java new file mode 100644 index 000000000..b1c317681 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transaction/MesWmTransactionDO.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.transaction; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 库存事务流水 DO + * + * 记录每一笔库存增减事件,系统自动生成,只读查询,不允许人工维护。 + */ +@TableName("mes_wm_transaction") +@KeySequence("mes_wm_transaction_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmTransactionDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + + // ==================== 业务归属 ==================== + + /** + * 事务类型 + * + * 枚举 {@link MesWmTransactionTypeEnum} + */ + private Integer type; + /** + * 本次变动数量 + * + * 正数=入库,负数=出库 + */ + private BigDecimal quantity; + + /** + * 业务类型 + * + * 对应 {@link MesBizTypeConstants} 中的常量 + */ + private Integer bizType; + /** + * 来源业务主单 ID + */ + private Long bizId; + /** + * 来源业务单号 + */ + private String bizCode; + /** + * 来源业务行 ID + */ + private Long bizLineId; + + /** + * 库存记录 ID + * + * 关联 {@link MesWmMaterialStockDO#getId()} + */ + private Long materialStockId; + /** + * 关联的事务 ID + * + * 关联 {@link #getId()},用于调拨等成对流水关联 + */ + private Long relatedTransactionId; + + // ==================== 物料维度 ==================== + + /** + * 物料 ID + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 批次 ID + * + * 关联 {@link MesWmBatchDO#getId()} + */ + private Long batchId; + /** + * 批次号 + * + * 关联 {@link MesWmBatchDO#getCode()} + */ + private String batchCode; + + // ==================== 库存位置 ==================== + + /** + * 仓库 ID + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库区 ID + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 库位 ID + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long areaId; + + // ==================== 时间 ==================== + + /** + * 事务发生时间 + */ + private LocalDateTime transactionTime; + /** + * ERP 账期 + */ + private LocalDateTime erpTime; + /** + * 入库时间 + */ + private LocalDateTime receiptTime; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDO.java new file mode 100644 index 000000000..d593a3eba --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDO.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransferStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransferTypeEnum; +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_wm_transfer") +@KeySequence("mes_wm_transfer_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmTransferDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 转移单编号 + */ + private String code; + /** + * 转移单名称 + */ + private String name; + /** + * 转移单类型 + * + * 枚举 {@link MesWmTransferTypeEnum} + */ + private Integer type; + + /** + * 是否配送 + */ + private Boolean deliveryFlag; + /** + * 收货人 + */ + private String recipientName; + /** + * 联系方式 + */ + private String recipientTelephone; + /** + * 目的地 + */ + private String destinationAddress; + /** + * 承运商 + */ + private String carrier; + /** + * 运输单号 + */ + private String shippingNumber; + /** + * 是否已确认 + */ + private Boolean confirmFlag; + + /** + * 转移日期 + */ + private LocalDateTime transferDate; + + /** + * 状态 + * + * 枚举 {@link MesWmTransferStatusEnum} + */ + private Integer status; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDetailDO.java new file mode 100644 index 000000000..b8c3b4414 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDetailDO.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 调拨明细 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_transfer_detail") +@KeySequence("mes_wm_transfer_detail_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmTransferDetailDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + + /** + * 转移单行编号 + * + * 关联 {@link MesWmTransferLineDO#getId()} + */ + private Long lineId; + /** + * 转移单编号 + * + * 关联 {@link MesWmTransferDO#getId()} + */ + private Long transferId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 上架数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + */ + private Long batchId; + + /** + * 移入仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long toWarehouseId; + /** + * 移入库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long toLocationId; + /** + * 移入库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long toAreaId; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferLineDO.java new file mode 100644 index 000000000..5bf09a9e0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferLineDO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * MES 转移单行 DO + * + * @author 芋道源码 + */ +@TableName("mes_wm_transfer_line") +@KeySequence("mes_wm_transfer_line_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmTransferLineDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 转移单编号 + * + * 关联 {@link MesWmTransferDO#getId()} + */ + private Long transferId; + /** + * 库存记录编号 + */ + private Long materialStockId; + /** + * 物料编号 + * + * 关联 {@link MesMdItemDO#getId()} + */ + private Long itemId; + /** + * 转移数量 + */ + private BigDecimal quantity; + /** + * 批次编号 + */ + private Long batchId; + + /** + * 移出仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long fromWarehouseId; + /** + * 移出库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long fromLocationId; + /** + * 移出库位编号 + * + * 关联 {@link MesWmWarehouseAreaDO#getId()} + */ + private Long fromAreaId; + + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseAreaDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseAreaDO.java new file mode 100644 index 000000000..ea9a3abdf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseAreaDO.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse; + +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.math.BigDecimal; + +/** + * MES 库位 DO + */ +@TableName("mes_wm_warehouse_area") +@KeySequence("mes_wm_warehouse_area_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmWarehouseAreaDO extends BaseDO { + + /** + * 虚拟线边库位编码(配合 {@link MesWmWarehouseDO#WIP_VIRTUAL_WAREHOUSE} 使用) + */ + public static final String WIP_VIRTUAL_AREA = "WIP_VIRTUAL_AREA"; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 库位编码 + */ + private String code; + /** + * 库位名称 + */ + private String name; + /** + * 库区编号 + * + * 关联 {@link MesWmWarehouseLocationDO#getId()} + */ + private Long locationId; + /** + * 面积 + */ + private BigDecimal area; + /** + * 最大载重 + */ + private BigDecimal maxLoad; + /** + * 位置 X + */ + private Integer positionX; + /** + * 位置 Y + */ + private Integer positionY; + /** + * 位置 Z + */ + private Integer positionZ; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + + /** + * 是否冻结 + */ + private Boolean frozen; + /** + * 是否允许物料混放 + */ + private Boolean allowItemMixing; + /** + * 是否允许批次混放 + */ + private Boolean allowBatchMixing; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseDO.java new file mode 100644 index 000000000..0c8a9b2e1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseDO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse; + +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.math.BigDecimal; + +/** + * MES 仓库 DO + */ +@TableName("mes_wm_warehouse") +@KeySequence("mes_wm_warehouse_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmWarehouseDO extends BaseDO { + + /** + * 虚拟线边库编码 + * + * 业务背景:在线边库模式下,物料从总仓库发放到车间,但未被工序消耗前,这部分物料属于在制品(WIP)。 + * 为了在系统中实现“发料与实际消耗”的解耦,并在不增加物理库位管理复杂度的前提下防止生产报工被负库存阻塞, + * 系统默认提供一个虚拟的线边库统管这些在制品。 + */ + public static final String WIP_VIRTUAL_WAREHOUSE = "WIP_VIRTUAL_WAREHOUSE"; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 仓库编码 + */ + private String code; + /** + * 仓库名称 + */ + private String name; + /** + * 仓库地址 + */ + private String address; + /** + * 面积 + */ + private BigDecimal area; + /** + * 负责人用户编号 + * + * 关联 system_users 表的 id 字段 + */ + private Long chargeUserId; + /** + * 是否冻结 + */ + private Boolean frozen; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseLocationDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseLocationDO.java new file mode 100644 index 000000000..bf062ce5d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseLocationDO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse; + +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.math.BigDecimal; + +/** + * MES 库区 DO + */ +@TableName("mes_wm_warehouse_location") +@KeySequence("mes_wm_warehouse_location_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesWmWarehouseLocationDO extends BaseDO { + + /** + * 虚拟线边库区编码(配合 {@link MesWmWarehouseDO#WIP_VIRTUAL_WAREHOUSE} 使用) + */ + public static final String WIP_VIRTUAL_LOCATION = "WIP_VIRTUAL_LOCATION"; + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 库区编码 + */ + private String code; + /** + * 库区名称 + */ + private String name; + /** + * 仓库编号 + * + * 关联 {@link MesWmWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 面积 + */ + private BigDecimal area; + /** + * 库位管理状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer areaStatus; + /** + * 是否冻结 + */ + private Boolean frozen; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/holiday/MesCalHolidayMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/holiday/MesCalHolidayMapper.java new file mode 100644 index 000000000..729bc4a49 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/holiday/MesCalHolidayMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.cal.holiday; + +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.cal.holiday.MesCalHolidayDO; +import org.apache.ibatis.annotations.Mapper; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * MES 假期设置 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesCalHolidayMapper extends BaseMapperX { + + default MesCalHolidayDO selectByDay(LocalDateTime day) { + return selectOne(MesCalHolidayDO::getDay, day); + } + + default List selectList(LocalDateTime startDay, LocalDateTime endDay) { + return selectList(new LambdaQueryWrapperX() + .betweenIfPresent(MesCalHolidayDO::getDay, startDay, endDay) + .orderByAsc(MesCalHolidayDO::getDay)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanMapper.java new file mode 100644 index 000000000..d2cd4b7f3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.cal.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 排班计划 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesCalPlanMapper extends BaseMapperX { + + default PageResult selectPage(MesCalPlanPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesCalPlanDO::getCode, reqVO.getCode()) + .likeIfPresent(MesCalPlanDO::getName, reqVO.getName()) + .eqIfPresent(MesCalPlanDO::getShiftType, reqVO.getShiftType()) + .eqIfPresent(MesCalPlanDO::getStatus, reqVO.getStatus()) + .eqIfPresent(MesCalPlanDO::getCalendarType, reqVO.getCalendarType()) + .betweenIfPresent(MesCalPlanDO::getStartDate, reqVO.getStartDate()) + .betweenIfPresent(MesCalPlanDO::getEndDate, reqVO.getEndDate()) + .orderByDesc(MesCalPlanDO::getId)); + } + + default MesCalPlanDO selectByCode(String code) { + return selectOne(MesCalPlanDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanShiftMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanShiftMapper.java new file mode 100644 index 000000000..d778a2117 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanShiftMapper.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.cal.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 计划班次 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesCalPlanShiftMapper extends BaseMapperX { + + default PageResult selectPage(MesCalPlanShiftPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesCalPlanShiftDO::getPlanId, reqVO.getPlanId()) + .likeIfPresent(MesCalPlanShiftDO::getName, reqVO.getName()) + .orderByAsc(MesCalPlanShiftDO::getSort)); + } + + default List selectListByPlanId(Long planId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesCalPlanShiftDO::getPlanId, planId) + .orderByAsc(MesCalPlanShiftDO::getSort)); + } + + default Long selectCountByPlanId(Long planId) { + return selectCount(MesCalPlanShiftDO::getPlanId, planId); + } + + default void deleteByPlanId(Long planId) { + delete(new LambdaQueryWrapperX() + .eq(MesCalPlanShiftDO::getPlanId, planId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanTeamMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanTeamMapper.java new file mode 100644 index 000000000..45450b829 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanTeamMapper.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.cal.plan; + +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.cal.plan.MesCalPlanTeamDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 计划班组关联 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesCalPlanTeamMapper extends BaseMapperX { + + default List selectListByPlanId(Long planId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesCalPlanTeamDO::getPlanId, planId) + .orderByDesc(MesCalPlanTeamDO::getId)); + } + + default Long selectCountByPlanId(Long planId) { + return selectCount(MesCalPlanTeamDO::getPlanId, planId); + } + + default MesCalPlanTeamDO selectByPlanIdAndTeamId(Long planId, Long teamId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesCalPlanTeamDO::getPlanId, planId) + .eq(MesCalPlanTeamDO::getTeamId, teamId)); + } + + default void deleteByPlanId(Long planId) { + delete(new LambdaQueryWrapperX() + .eq(MesCalPlanTeamDO::getPlanId, planId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamMapper.java new file mode 100644 index 000000000..0befc1cae --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.cal.team; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 班组 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesCalTeamMapper extends BaseMapperX { + + default PageResult selectPage(MesCalTeamPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesCalTeamDO::getCode, reqVO.getCode()) + .likeIfPresent(MesCalTeamDO::getName, reqVO.getName()) + .eqIfPresent(MesCalTeamDO::getCalendarType, reqVO.getCalendarType()) + .orderByDesc(MesCalTeamDO::getId)); + } + + default MesCalTeamDO selectByCode(String code) { + return selectOne(MesCalTeamDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamMemberMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamMemberMapper.java new file mode 100644 index 000000000..ff9cd8be6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamMemberMapper.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.cal.team; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * MES 班组成员 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesCalTeamMemberMapper extends BaseMapperX { + + default PageResult selectPage(MesCalTeamMemberPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesCalTeamMemberDO::getTeamId, reqVO.getTeamId()) + .orderByDesc(MesCalTeamMemberDO::getId)); + } + + default List selectListByTeamId(Long teamId) { + return selectList(MesCalTeamMemberDO::getTeamId, teamId); + } + + default List selectListByTeamIds(Collection teamIds) { + return selectList(MesCalTeamMemberDO::getTeamId, teamIds); + } + + default MesCalTeamMemberDO selectByUserId(Long userId) { + return selectOne(MesCalTeamMemberDO::getUserId, userId); + } + + default void deleteByTeamId(Long teamId) { + delete(MesCalTeamMemberDO::getTeamId, teamId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamShiftMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamShiftMapper.java new file mode 100644 index 000000000..c882f2017 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/team/MesCalTeamShiftMapper.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.cal.team; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 班组排班 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesCalTeamShiftMapper extends BaseMapperX { + + default List selectList(MesCalTeamShiftListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(MesCalTeamShiftDO::getTeamId, reqVO.getTeamId()) + .inIfPresent(MesCalTeamShiftDO::getTeamId, reqVO.getTeamIds()) + .eqIfPresent(MesCalTeamShiftDO::getPlanId, reqVO.getPlanId()) + .geIfPresent(MesCalTeamShiftDO::getDay, reqVO.getStartDay()) + .leIfPresent(MesCalTeamShiftDO::getDay, reqVO.getEndDay()) + .orderByAsc(MesCalTeamShiftDO::getDay) + .orderByAsc(MesCalTeamShiftDO::getSort)); + } + + default List selectListByPlanId(Long planId) { + return selectList(MesCalTeamShiftDO::getPlanId, planId); + } + + default void deleteByPlanId(Long planId) { + delete(MesCalTeamShiftDO::getPlanId, planId); + } + + default void deleteByTeamId(Long teamId) { + delete(MesCalTeamShiftDO::getTeamId, teamId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanMachineryMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanMachineryMapper.java new file mode 100644 index 000000000..8ff3c6544 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanMachineryMapper.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.checkplan; + +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.dv.checkplan.MesDvCheckPlanMachineryDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 点检保养方案设备 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvCheckPlanMachineryMapper extends BaseMapperX { + + default List selectListByPlanId(Long planId) { + return selectList(MesDvCheckPlanMachineryDO::getPlanId, planId); + } + + default Long selectCountByPlanId(Long planId) { + return selectCount(MesDvCheckPlanMachineryDO::getPlanId, planId); + } + + default void deleteByPlanId(Long planId) { + delete(new LambdaQueryWrapperX() + .eq(MesDvCheckPlanMachineryDO::getPlanId, planId)); + } + + default Long selectCountByMachineryId(Long machineryId) { + return selectCount(MesDvCheckPlanMachineryDO::getMachineryId, machineryId); + } + + default List selectListByMachineryId(Long machineryId) { + return selectList(MesDvCheckPlanMachineryDO::getMachineryId, machineryId); + } + + default MesDvCheckPlanMachineryDO selectByPlanIdAndMachineryId(Long planId, Long machineryId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesDvCheckPlanMachineryDO::getPlanId, planId) + .eq(MesDvCheckPlanMachineryDO::getMachineryId, machineryId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanMapper.java new file mode 100644 index 000000000..eb2421c33 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.checkplan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 点检保养方案 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvCheckPlanMapper extends BaseMapperX { + + default PageResult selectPage(MesDvCheckPlanPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesDvCheckPlanDO::getCode, reqVO.getCode()) + .likeIfPresent(MesDvCheckPlanDO::getName, reqVO.getName()) + .eqIfPresent(MesDvCheckPlanDO::getType, reqVO.getType()) + .eqIfPresent(MesDvCheckPlanDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesDvCheckPlanDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesDvCheckPlanDO::getId)); + } + + default MesDvCheckPlanDO selectByCode(String code) { + return selectOne(MesDvCheckPlanDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanSubjectMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanSubjectMapper.java new file mode 100644 index 000000000..5f29147f3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkplan/MesDvCheckPlanSubjectMapper.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.checkplan; + +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.dv.checkplan.MesDvCheckPlanSubjectDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 点检保养方案项目 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvCheckPlanSubjectMapper extends BaseMapperX { + + default List selectListByPlanId(Long planId) { + return selectList(MesDvCheckPlanSubjectDO::getPlanId, planId); + } + + default Long selectCountByPlanId(Long planId) { + return selectCount(MesDvCheckPlanSubjectDO::getPlanId, planId); + } + + default void deleteByPlanId(Long planId) { + delete(new LambdaQueryWrapperX() + .eq(MesDvCheckPlanSubjectDO::getPlanId, planId)); + } + + default Long selectCountBySubjectId(Long subjectId) { + return selectCount(MesDvCheckPlanSubjectDO::getSubjectId, subjectId); + } + + default MesDvCheckPlanSubjectDO selectByPlanIdAndSubjectId(Long planId, Long subjectId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesDvCheckPlanSubjectDO::getPlanId, planId) + .eq(MesDvCheckPlanSubjectDO::getSubjectId, subjectId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkrecord/MesDvCheckRecordLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkrecord/MesDvCheckRecordLineMapper.java new file mode 100644 index 000000000..ab217ec93 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkrecord/MesDvCheckRecordLineMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.checkrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 设备点检记录明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvCheckRecordLineMapper extends BaseMapperX { + + default PageResult selectPage(MesDvCheckRecordLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesDvCheckRecordLineDO::getRecordId, reqVO.getRecordId()) + .orderByDesc(MesDvCheckRecordLineDO::getId)); + } + + default List selectListByRecordId(Long recordId) { + return selectList(MesDvCheckRecordLineDO::getRecordId, recordId); + } + + default int deleteByRecordId(Long recordId) { + return delete(MesDvCheckRecordLineDO::getRecordId, recordId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkrecord/MesDvCheckRecordMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkrecord/MesDvCheckRecordMapper.java new file mode 100644 index 000000000..4eb2b5ceb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/checkrecord/MesDvCheckRecordMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.checkrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 设备点检记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvCheckRecordMapper extends BaseMapperX { + + default PageResult selectPage(MesDvCheckRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesDvCheckRecordDO::getPlanId, reqVO.getPlanId()) + .eqIfPresent(MesDvCheckRecordDO::getMachineryId, reqVO.getMachineryId()) + .eqIfPresent(MesDvCheckRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MesDvCheckRecordDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesDvCheckRecordDO::getCheckTime, reqVO.getCheckTime()) + .orderByDesc(MesDvCheckRecordDO::getId)); + } + + default Long selectCountByMachineryId(Long machineryId) { + return selectCount(MesDvCheckRecordDO::getMachineryId, machineryId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/machinery/MesDvMachineryMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/machinery/MesDvMachineryMapper.java new file mode 100644 index 000000000..5e39c3de7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/machinery/MesDvMachineryMapper.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.machinery; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 设备台账 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvMachineryMapper extends BaseMapperX { + + default PageResult selectPage(MesDvMachineryPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesDvMachineryDO::getCode, reqVO.getCode()) + .likeIfPresent(MesDvMachineryDO::getName, reqVO.getName()) + .likeIfPresent(MesDvMachineryDO::getBrand, reqVO.getBrand()) + .eqIfPresent(MesDvMachineryDO::getMachineryTypeId, reqVO.getMachineryTypeId()) + .inIfPresent(MesDvMachineryDO::getMachineryTypeId, reqVO.getMachineryTypeIds()) + .eqIfPresent(MesDvMachineryDO::getWorkshopId, reqVO.getWorkshopId()) + .eqIfPresent(MesDvMachineryDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesDvMachineryDO::getId)); + } + + default MesDvMachineryDO selectByCode(String code) { + return selectOne(MesDvMachineryDO::getCode, code); + } + + default Long selectCountByMachineryTypeId(Long machineryTypeId) { + return selectCount(MesDvMachineryDO::getMachineryTypeId, machineryTypeId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/machinery/MesDvMachineryTypeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/machinery/MesDvMachineryTypeMapper.java new file mode 100644 index 000000000..232fdb2d3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/machinery/MesDvMachineryTypeMapper.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.machinery; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 设备类型 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvMachineryTypeMapper extends BaseMapperX { + + default List selectList(MesDvMachineryTypeListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(MesDvMachineryTypeDO::getName, reqVO.getName()) + .eqIfPresent(MesDvMachineryTypeDO::getStatus, reqVO.getStatus()) + .orderByAsc(MesDvMachineryTypeDO::getSort) + .orderByDesc(MesDvMachineryTypeDO::getId)); + } + + default List selectList() { + return selectList(new LambdaQueryWrapperX() + .orderByAsc(MesDvMachineryTypeDO::getSort) + .orderByDesc(MesDvMachineryTypeDO::getId)); + } + + default MesDvMachineryTypeDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesDvMachineryTypeDO::getParentId, parentId) + .eq(MesDvMachineryTypeDO::getName, name)); + } + + default MesDvMachineryTypeDO selectByCode(String code) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesDvMachineryTypeDO::getCode, code)); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(MesDvMachineryTypeDO::getParentId, parentId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/maintenrecord/MesDvMaintenRecordLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/maintenrecord/MesDvMaintenRecordLineMapper.java new file mode 100644 index 000000000..518825816 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/maintenrecord/MesDvMaintenRecordLineMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.maintenrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 设备保养记录明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvMaintenRecordLineMapper extends BaseMapperX { + + default PageResult selectPage(MesDvMaintenRecordLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesDvMaintenRecordLineDO::getRecordId, reqVO.getRecordId()) + .orderByDesc(MesDvMaintenRecordLineDO::getId)); + } + + default List selectListByRecordId(Long recordId) { + return selectList(MesDvMaintenRecordLineDO::getRecordId, recordId); + } + + default int deleteByRecordId(Long recordId) { + return delete(MesDvMaintenRecordLineDO::getRecordId, recordId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/maintenrecord/MesDvMaintenRecordMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/maintenrecord/MesDvMaintenRecordMapper.java new file mode 100644 index 000000000..e64ead55c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/maintenrecord/MesDvMaintenRecordMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.maintenrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 设备保养记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvMaintenRecordMapper extends BaseMapperX { + + default PageResult selectPage(MesDvMaintenRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesDvMaintenRecordDO::getPlanId, reqVO.getPlanId()) + .eqIfPresent(MesDvMaintenRecordDO::getMachineryId, reqVO.getMachineryId()) + .eqIfPresent(MesDvMaintenRecordDO::getUserId, reqVO.getUserId()) + .betweenIfPresent(MesDvMaintenRecordDO::getMaintenTime, reqVO.getMaintenTime()) + .orderByDesc(MesDvMaintenRecordDO::getId)); + } + + default Long selectCountByMachineryId(Long machineryId) { + return selectCount(MesDvMaintenRecordDO::getMachineryId, machineryId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/repair/MesDvRepairLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/repair/MesDvRepairLineMapper.java new file mode 100644 index 000000000..af067e550 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/repair/MesDvRepairLineMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.repair; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 维修工单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvRepairLineMapper extends BaseMapperX { + + default PageResult selectPage(MesDvRepairLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesDvRepairLineDO::getRepairId, reqVO.getRepairId()) + .orderByDesc(MesDvRepairLineDO::getId)); + } + + default List selectListByRepairId(Long repairId) { + return selectList(MesDvRepairLineDO::getRepairId, repairId); + } + + default int deleteByRepairId(Long repairId) { + return delete(MesDvRepairLineDO::getRepairId, repairId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/repair/MesDvRepairMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/repair/MesDvRepairMapper.java new file mode 100644 index 000000000..bd016f75e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/repair/MesDvRepairMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.repair; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 维修工单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesDvRepairMapper extends BaseMapperX { + + default PageResult selectPage(MesDvRepairPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesDvRepairDO::getCode, reqVO.getCode()) + .likeIfPresent(MesDvRepairDO::getName, reqVO.getName()) + .eqIfPresent(MesDvRepairDO::getMachineryId, reqVO.getMachineryId()) + .eqIfPresent(MesDvRepairDO::getResult, reqVO.getResult()) + .eqIfPresent(MesDvRepairDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesDvRepairDO::getRequireDate, reqVO.getRequireDate()) + .orderByDesc(MesDvRepairDO::getId)); + } + + default MesDvRepairDO selectByCode(String code) { + return selectOne(MesDvRepairDO::getCode, code); + } + + default Long selectCountByMachineryId(Long machineryId) { + return selectCount(MesDvRepairDO::getMachineryId, machineryId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/subject/MesDvSubjectMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/subject/MesDvSubjectMapper.java new file mode 100644 index 000000000..99dd62722 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/subject/MesDvSubjectMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.dv.subject; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MesDvSubjectMapper extends BaseMapperX { + + default PageResult selectPage(MesDvSubjectPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesDvSubjectDO::getCode, reqVO.getCode()) + .likeIfPresent(MesDvSubjectDO::getName, reqVO.getName()) + .eqIfPresent(MesDvSubjectDO::getType, reqVO.getType()) + .eqIfPresent(MesDvSubjectDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesDvSubjectDO::getId)); + } + + default MesDvSubjectDO selectByCode(String code) { + return selectOne(MesDvSubjectDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/home/MesHomeStatisticsMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/home/MesHomeStatisticsMapper.java new file mode 100644 index 000000000..f9d6c6d96 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/home/MesHomeStatisticsMapper.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.home; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +/** + * MES 首页统计 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesHomeStatisticsMapper { + + /** + * 按状态统计工单数量 + * + * @return [{ "status": 0, "count": 5 }, ...] + */ + List> selectWorkOrderCountGroupByStatus(); + + /** + * 统计报工产量合计 + * + * @param beginTime >= 开始时间 + * @param endTime < 结束时间 + * @return [feedbackQuantity, qualifiedQuantity, unqualifiedQuantity] + */ + Map selectFeedbackSummary(@Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + + /** + * 按设备状态统计设备台数 + * + * @return [{ "status": 1, "count": 3 }, ...] + */ + List> selectMachineryCountGroupByStatus(); + + /** + * 统计未处置安灯记录数 + * + * @return 数量 + */ + Long selectAndonActiveCount(); + + /** + * 统计未完成维修工单数(草稿 + 维修中 + 待验收) + * + * @return 数量 + */ + Long selectRepairActiveCount(); + + /** + * 按天聚合报工产量(近 N 天) + * + * @param beginTime >= 开始时间 + * @param endTime < 结束时间 + * @return [{ "date": "2026-04-05", "quantity": 1234, "qualifiedQuantity": 1200, "unqualifiedQuantity": 34 }, ...] + */ + List> selectDailyFeedbackTrend(@Param("beginTime") LocalDateTime beginTime, + @Param("endTime") LocalDateTime endTime); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodePartMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodePartMapper.java new file mode 100644 index 000000000..9b7a5dfad --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodePartMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.autocode; + +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.md.autocode.MesMdAutoCodePartDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 编码规则组成 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdAutoCodePartMapper extends BaseMapperX { + + default List selectListByRuleId(Long ruleId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesMdAutoCodePartDO::getRuleId, ruleId) + .orderByAsc(MesMdAutoCodePartDO::getSort)); + } + + default void deleteByRuleId(Long ruleId) { + delete(MesMdAutoCodePartDO::getRuleId, ruleId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRecordMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRecordMapper.java new file mode 100644 index 000000000..13aa301f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRecordMapper.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.autocode; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 编码生成记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdAutoCodeRecordMapper extends BaseMapperX { + + default MesMdAutoCodeRecordDO selectByResult(String result) { + return selectOne(MesMdAutoCodeRecordDO::getResult, result); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRuleMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRuleMapper.java new file mode 100644 index 000000000..43b75429f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRuleMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.autocode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRulePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 编码规则 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdAutoCodeRuleMapper extends BaseMapperX { + + default PageResult selectPage(MesMdAutoCodeRulePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesMdAutoCodeRuleDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdAutoCodeRuleDO::getName, reqVO.getName()) + .eqIfPresent(MesMdAutoCodeRuleDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesMdAutoCodeRuleDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesMdAutoCodeRuleDO::getId)); + } + + default MesMdAutoCodeRuleDO selectByCode(String code) { + return selectOne(MesMdAutoCodeRuleDO::getCode, code); + } + + default List selectListByStatus(Integer status) { + return selectList(MesMdAutoCodeRuleDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/client/MesMdClientMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/client/MesMdClientMapper.java new file mode 100644 index 000000000..a1e0f9970 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/client/MesMdClientMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.client; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import org.apache.ibatis.annotations.Mapper; + + + + +/** + * MES 客户 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdClientMapper extends BaseMapperX { + + default PageResult selectPage(MesMdClientPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesMdClientDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdClientDO::getName, reqVO.getName()) + .likeIfPresent(MesMdClientDO::getNickname, reqVO.getNickname()) + .likeIfPresent(MesMdClientDO::getEnglishName, reqVO.getEnglishName()) + .eqIfPresent(MesMdClientDO::getType, reqVO.getType()) + .eqIfPresent(MesMdClientDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesMdClientDO::getId)); + } + + default MesMdClientDO selectByCode(String code) { + return selectOne(MesMdClientDO::getCode, code); + } + + default MesMdClientDO selectByName(String name) { + return selectOne(MesMdClientDO::getName, name); + } + + default MesMdClientDO selectByNickname(String nickname) { + return selectOne(MesMdClientDO::getNickname, nickname); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemBatchConfigMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemBatchConfigMapper.java new file mode 100644 index 000000000..e6ad43c8f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemBatchConfigMapper.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.item; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MesMdItemBatchConfigMapper extends BaseMapperX { + + default MesMdItemBatchConfigDO selectByItemId(Long itemId) { + return selectOne(MesMdItemBatchConfigDO::getItemId, itemId); + } + + default int deleteByItemId(Long itemId) { + return delete(MesMdItemBatchConfigDO::getItemId, itemId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java new file mode 100644 index 000000000..64bfe6b24 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; + +/** + * MES 物料产品 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdItemMapper extends BaseMapperX { + + default PageResult selectPage(MesMdItemPageReqVO reqVO, Collection itemTypeIds) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesMdItemDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdItemDO::getName, reqVO.getName()) + .inIfPresent(MesMdItemDO::getItemTypeId, itemTypeIds) + .eqIfPresent(MesMdItemDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesMdItemDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesMdItemDO::getId)); + } + + default MesMdItemDO selectByCode(String code) { + return selectOne(MesMdItemDO::getCode, code); + } + + default MesMdItemDO selectByName(String name) { + return selectOne(MesMdItemDO::getName, name); + } + + default Long selectCountByItemTypeId(Long itemTypeId) { + return selectCount(MesMdItemDO::getItemTypeId, itemTypeId); + } + + default Long selectCountByUnitMeasureId(Long unitMeasureId) { + return selectCount(MesMdItemDO::getUnitMeasureId, unitMeasureId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemTypeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemTypeMapper.java new file mode 100644 index 000000000..6dbddff2c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemTypeMapper.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.item; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 物料产品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdItemTypeMapper extends BaseMapperX { + + default List selectList(MesMdItemTypeListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(MesMdItemTypeDO::getName, reqVO.getName()) + .eqIfPresent(MesMdItemTypeDO::getStatus, reqVO.getStatus()) + .orderByAsc(MesMdItemTypeDO::getSort)); + } + + default MesMdItemTypeDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(MesMdItemTypeDO::getParentId, parentId, MesMdItemTypeDO::getName, name); + } + + default MesMdItemTypeDO selectByParentIdAndCode(Long parentId, String code) { + return selectOne(MesMdItemTypeDO::getParentId, parentId, MesMdItemTypeDO::getCode, code); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(MesMdItemTypeDO::getParentId, parentId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductBomMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductBomMapper.java new file mode 100644 index 000000000..daadf607b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductBomMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * MES 产品BOM Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdProductBomMapper extends BaseMapperX { + + default PageResult selectPage(MesMdProductBomPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(MesMdProductBomDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesMdProductBomDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesMdProductBomDO::getId)); + } + + default List selectByItemId(Long itemId) { + return selectList(MesMdProductBomDO::getItemId, itemId); + } + + default List selectByItemIds(Collection itemIds) { + return selectList(MesMdProductBomDO::getItemId, itemIds); + } + + default List selectAll() { + return selectList(); + } + + default void deleteByItemId(Long itemId) { + delete(MesMdProductBomDO::getItemId, itemId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductSipMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductSipMapper.java new file mode 100644 index 000000000..aee9cd7d7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductSipMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip.MesMdProductSipPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductSipDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 产品SIP Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdProductSipMapper extends BaseMapperX { + + default PageResult selectPage(MesMdProductSipPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(MesMdProductSipDO::getItemId, reqVO.getItemId()) + .likeIfPresent(MesMdProductSipDO::getTitle, reqVO.getTitle()) + .orderByAsc(MesMdProductSipDO::getSort)); + } + + default List selectByItemId(Long itemId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesMdProductSipDO::getItemId, itemId) + .orderByAsc(MesMdProductSipDO::getSort)); + } + + default Long selectCountByItemIdAndSort(Long itemId, Integer sort, Long excludeId) { + return selectCount(new LambdaQueryWrapperX() + .eq(MesMdProductSipDO::getItemId, itemId) + .eq(MesMdProductSipDO::getSort, sort) + .neIfPresent(MesMdProductSipDO::getId, excludeId)); + } + + default void deleteByItemId(Long itemId) { + delete(MesMdProductSipDO::getItemId, itemId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductSopMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductSopMapper.java new file mode 100644 index 000000000..f5f97fd6c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdProductSopMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop.MesMdProductSopPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductSopDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 产品SOP Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdProductSopMapper extends BaseMapperX { + + default PageResult selectPage(MesMdProductSopPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(MesMdProductSopDO::getItemId, reqVO.getItemId()) + .likeIfPresent(MesMdProductSopDO::getTitle, reqVO.getTitle()) + .orderByAsc(MesMdProductSopDO::getSort)); + } + + default List selectByItemId(Long itemId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesMdProductSopDO::getItemId, itemId) + .orderByAsc(MesMdProductSopDO::getSort)); + } + + default Long selectCountByItemIdAndSort(Long itemId, Integer sort, Long excludeId) { + return selectCount(new LambdaQueryWrapperX() + .eq(MesMdProductSopDO::getItemId, itemId) + .eq(MesMdProductSopDO::getSort, sort) + .neIfPresent(MesMdProductSopDO::getId, excludeId)); + } + + default void deleteByItemId(Long itemId) { + delete(MesMdProductSopDO::getItemId, itemId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/unitmeasure/MesMdUnitMeasureMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/unitmeasure/MesMdUnitMeasureMapper.java new file mode 100644 index 000000000..cb9a2bf03 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/unitmeasure/MesMdUnitMeasureMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.unitmeasure; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasurePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 计量单位 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdUnitMeasureMapper extends BaseMapperX { + + default PageResult selectPage(MesMdUnitMeasurePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesMdUnitMeasureDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdUnitMeasureDO::getName, reqVO.getName()) + .eqIfPresent(MesMdUnitMeasureDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesMdUnitMeasureDO::getId)); + } + + default MesMdUnitMeasureDO selectByCode(String code) { + return selectOne(MesMdUnitMeasureDO::getCode, code); + } + + default List selectListByStatus(Integer status) { + return selectList(MesMdUnitMeasureDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/vendor/MesMdVendorMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/vendor/MesMdVendorMapper.java new file mode 100644 index 000000000..ac6feeb29 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/vendor/MesMdVendorMapper.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.vendor; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 供应商 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdVendorMapper extends BaseMapperX { + + default PageResult selectPage(MesMdVendorPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesMdVendorDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdVendorDO::getName, reqVO.getName()) + .likeIfPresent(MesMdVendorDO::getNickname, reqVO.getNickname()) + .likeIfPresent(MesMdVendorDO::getEnglishName, reqVO.getEnglishName()) + .eqIfPresent(MesMdVendorDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesMdVendorDO::getId)); + } + + default MesMdVendorDO selectByCode(String code) { + return selectOne(MesMdVendorDO::getCode, code); + } + + default MesMdVendorDO selectByName(String name) { + return selectOne(MesMdVendorDO::getName, name); + } + + default MesMdVendorDO selectByNickname(String nickname) { + return selectOne(MesMdVendorDO::getNickname, nickname); + } +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkshopMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkshopMapper.java new file mode 100644 index 000000000..824bfdcd8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkshopMapper.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.workstation; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 车间 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdWorkshopMapper extends BaseMapperX { + + default PageResult selectPage(MesMdWorkshopPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesMdWorkshopDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdWorkshopDO::getName, reqVO.getName()) + .eqIfPresent(MesMdWorkshopDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesMdWorkshopDO::getId)); + } + + default MesMdWorkshopDO selectByCode(String code) { + return selectOne(MesMdWorkshopDO::getCode, code); + } + + default MesMdWorkshopDO selectByName(String name) { + return selectOne(MesMdWorkshopDO::getName, name); + } + + default List selectListByStatus(Integer status) { + return selectList(MesMdWorkshopDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMachineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMachineMapper.java new file mode 100644 index 000000000..1ff2aa362 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMachineMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.workstation; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationMachineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 设备资源 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdWorkstationMachineMapper extends BaseMapperX { + + default List selectListByWorkstationId(Long workstationId) { + return selectList(MesMdWorkstationMachineDO::getWorkstationId, workstationId); + } + + default MesMdWorkstationMachineDO selectByMachineryId(Long machineryId) { + return selectOne(MesMdWorkstationMachineDO::getMachineryId, machineryId); + } + + default void deleteByWorkstationId(Long workstationId) { + delete(MesMdWorkstationMachineDO::getWorkstationId, workstationId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMapper.java new file mode 100644 index 000000000..8819cf60c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMapper.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.workstation; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 工作站 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdWorkstationMapper extends BaseMapperX { + + default PageResult selectPage(MesMdWorkstationPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesMdWorkstationDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdWorkstationDO::getName, reqVO.getName()) + .eqIfPresent(MesMdWorkstationDO::getWorkshopId, reqVO.getWorkshopId()) + .eqIfPresent(MesMdWorkstationDO::getProcessId, reqVO.getProcessId()) + .eqIfPresent(MesMdWorkstationDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesMdWorkstationDO::getId)); + } + + default MesMdWorkstationDO selectByCode(String code) { + return selectOne(MesMdWorkstationDO::getCode, code); + } + + default MesMdWorkstationDO selectByName(String name) { + return selectOne(MesMdWorkstationDO::getName, name); + } + + default List selectListByStatus(Integer status) { + return selectList(MesMdWorkstationDO::getStatus, status); + } + + default Long selectCountByWarehouseId(Long warehouseId) { + return selectCount(MesMdWorkstationDO::getWarehouseId, warehouseId); + } + + default Long selectCountByLocationId(Long locationId) { + return selectCount(MesMdWorkstationDO::getLocationId, locationId); + } + + default Long selectCountByAreaId(Long areaId) { + return selectCount(MesMdWorkstationDO::getAreaId, areaId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationToolMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationToolMapper.java new file mode 100644 index 000000000..fcb8268f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationToolMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.workstation; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationToolDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 工装夹具资源 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdWorkstationToolMapper extends BaseMapperX { + + default List selectListByWorkstationId(Long workstationId) { + return selectList(MesMdWorkstationToolDO::getWorkstationId, workstationId); + } + + default MesMdWorkstationToolDO selectByWorkstationIdAndToolTypeId(Long workstationId, Long toolTypeId) { + return selectOne(new LambdaQueryWrapper() + .eq(MesMdWorkstationToolDO::getWorkstationId, workstationId) + .eq(MesMdWorkstationToolDO::getToolTypeId, toolTypeId)); + } + + default void deleteByWorkstationId(Long workstationId) { + delete(MesMdWorkstationToolDO::getWorkstationId, workstationId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationWorkerMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationWorkerMapper.java new file mode 100644 index 000000000..0334c1e84 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationWorkerMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.workstation; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationWorkerDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 人力资源 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdWorkstationWorkerMapper extends BaseMapperX { + + default List selectListByWorkstationId(Long workstationId) { + return selectList(MesMdWorkstationWorkerDO::getWorkstationId, workstationId); + } + + default MesMdWorkstationWorkerDO selectByWorkstationIdAndPostId(Long workstationId, Long postId) { + return selectOne(new LambdaQueryWrapper() + .eq(MesMdWorkstationWorkerDO::getWorkstationId, workstationId) + .eq(MesMdWorkstationWorkerDO::getPostId, postId)); + } + + default void deleteByWorkstationId(Long workstationId) { + delete(MesMdWorkstationWorkerDO::getWorkstationId, workstationId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/andon/MesProAndonConfigMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/andon/MesProAndonConfigMapper.java new file mode 100644 index 000000000..6ec42e495 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/andon/MesProAndonConfigMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.andon; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config.MesProAndonConfigPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonConfigDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 安灯呼叫配置 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProAndonConfigMapper extends BaseMapperX { + + default PageResult selectPage(MesProAndonConfigPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesProAndonConfigDO::getReason, reqVO.getReason()) + .eqIfPresent(MesProAndonConfigDO::getLevel, reqVO.getLevel()) + .orderByDesc(MesProAndonConfigDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/andon/MesProAndonRecordMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/andon/MesProAndonRecordMapper.java new file mode 100644 index 000000000..a3092eed4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/andon/MesProAndonRecordMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.andon; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 安灯呼叫记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProAndonRecordMapper extends BaseMapperX { + + default PageResult selectPage(MesProAndonRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesProAndonRecordDO::getWorkstationId, reqVO.getWorkstationId()) + .eqIfPresent(MesProAndonRecordDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MesProAndonRecordDO::getHandlerUserId, reqVO.getHandlerUserId()) + .eqIfPresent(MesProAndonRecordDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesProAndonRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesProAndonRecordDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/card/MesProCardMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/card/MesProCardMapper.java new file mode 100644 index 000000000..d85a4ecfb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/card/MesProCardMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.card; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 生产流转卡 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProCardMapper extends BaseMapperX { + + default PageResult selectPage(MesProCardPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesProCardDO::getCode, reqVO.getCode()) + .eqIfPresent(MesProCardDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesProCardDO::getItemId, reqVO.getItemId()) + .likeIfPresent(MesProCardDO::getBatchCode, reqVO.getBatchCode()) + .orderByDesc(MesProCardDO::getId)); + } + + default MesProCardDO selectByCode(String code) { + return selectOne(MesProCardDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/card/MesProCardProcessMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/card/MesProCardProcessMapper.java new file mode 100644 index 000000000..1456d917a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/card/MesProCardProcessMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.card; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process.MesProCardProcessPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardProcessDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 流转卡工序记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProCardProcessMapper extends BaseMapperX { + + default PageResult selectPage(MesProCardProcessPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesProCardProcessDO::getCardId, reqVO.getCardId()) + .eqIfPresent(MesProCardProcessDO::getProcessId, reqVO.getProcessId()) + .eqIfPresent(MesProCardProcessDO::getWorkstationId, reqVO.getWorkstationId()) + .eqIfPresent(MesProCardProcessDO::getUserId, reqVO.getUserId()) + .orderByAsc(MesProCardProcessDO::getSort)); + } + + default List selectListByCardId(Long cardId) { + return selectList(MesProCardProcessDO::getCardId, cardId); + } + + default void deleteByCardId(Long cardId) { + delete(MesProCardProcessDO::getCardId, cardId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/feedback/MesProFeedbackMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/feedback/MesProFeedbackMapper.java new file mode 100644 index 000000000..6308ae9a0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/feedback/MesProFeedbackMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 生产报工 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProFeedbackMapper extends BaseMapperX { + + default PageResult selectPage(MesProFeedbackPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesProFeedbackDO::getCode, reqVO.getCode()) + .eqIfPresent(MesProFeedbackDO::getType, reqVO.getType()) + .eqIfPresent(MesProFeedbackDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesProFeedbackDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesProFeedbackDO::getFeedbackTime, reqVO.getFeedbackTime()) + .eqIfPresent(MesProFeedbackDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesProFeedbackDO::getFeedbackUserId, reqVO.getFeedbackUserId()) + .eqIfPresent(MesProFeedbackDO::getCreator, reqVO.getCreator()) + .orderByDesc(MesProFeedbackDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/process/MesProProcessContentMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/process/MesProProcessContentMapper.java new file mode 100644 index 000000000..bfa21e0aa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/process/MesProProcessContentMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.process; + +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.process.MesProProcessContentDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 生产工序内容 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProProcessContentMapper extends BaseMapperX { + + default List selectListByProcessId(Long processId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesProProcessContentDO::getProcessId, processId) + .orderByAsc(MesProProcessContentDO::getSort)); + } + + default void deleteByProcessId(Long processId) { + delete(new LambdaQueryWrapperX() + .eq(MesProProcessContentDO::getProcessId, processId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/process/MesProProcessMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/process/MesProProcessMapper.java new file mode 100644 index 000000000..91260deec --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/process/MesProProcessMapper.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.process; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcessPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 生产工序 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProProcessMapper extends BaseMapperX { + + default PageResult selectPage(MesProProcessPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesProProcessDO::getCode, reqVO.getCode()) + .likeIfPresent(MesProProcessDO::getName, reqVO.getName()) + .eqIfPresent(MesProProcessDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesProProcessDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesProProcessDO::getId)); + } + + default List selectList(MesProProcessPageReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(MesProProcessDO::getCode, reqVO.getCode()) + .likeIfPresent(MesProProcessDO::getName, reqVO.getName()) + .eqIfPresent(MesProProcessDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesProProcessDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesProProcessDO::getId)); + } + + default MesProProcessDO selectByCode(String code) { + return selectOne(MesProProcessDO::getCode, code); + } + + default MesProProcessDO selectByName(String name) { + return selectOne(MesProProcessDO::getName, name); + } + + default List selectListByStatus(Integer status) { + return selectList(MesProProcessDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteMapper.java new file mode 100644 index 000000000..e98ec243e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.route; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.MesProRoutePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 工艺路线 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProRouteMapper extends BaseMapperX { + + default PageResult selectPage(MesProRoutePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesProRouteDO::getCode, reqVO.getCode()) + .likeIfPresent(MesProRouteDO::getName, reqVO.getName()) + .eqIfPresent(MesProRouteDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesProRouteDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesProRouteDO::getId)); + } + + default MesProRouteDO selectByCode(String code) { + return selectOne(MesProRouteDO::getCode, code); + } + + default List selectListByStatus(Integer status) { + return selectList(MesProRouteDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProcessMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProcessMapper.java new file mode 100644 index 000000000..ee24ef304 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProcessMapper.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.route; + +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.route.MesProRouteProcessDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * MES 工艺路线工序 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProRouteProcessMapper extends BaseMapperX { + + default List selectListByRouteId(Long routeId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesProRouteProcessDO::getRouteId, routeId) + .orderByAsc(MesProRouteProcessDO::getSort)); + } + + default MesProRouteProcessDO selectByRouteIdAndSort(Long routeId, Integer sort) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesProRouteProcessDO::getRouteId, routeId) + .eq(MesProRouteProcessDO::getSort, sort)); + } + + default MesProRouteProcessDO selectByRouteIdAndProcessId(Long routeId, Long processId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesProRouteProcessDO::getRouteId, routeId) + .eq(MesProRouteProcessDO::getProcessId, processId)); + } + + default MesProRouteProcessDO selectKeyProcessByRouteId(Long routeId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesProRouteProcessDO::getRouteId, routeId) + .eq(MesProRouteProcessDO::getKeyFlag, true)); + } + + default void deleteByRouteId(Long routeId) { + delete(new LambdaQueryWrapperX() + .eq(MesProRouteProcessDO::getRouteId, routeId)); + } + + default List selectListByProcessId(Long processId) { + return selectList(MesProRouteProcessDO::getProcessId, processId); + } + + default List selectListByRouteIds(Collection routeIds) { + return selectList(new LambdaQueryWrapperX() + .in(MesProRouteProcessDO::getRouteId, routeIds)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProductBomMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProductBomMapper.java new file mode 100644 index 000000000..832c54937 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProductBomMapper.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.route; + +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.route.MesProRouteProductBomDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 工艺路线产品 BOM Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProRouteProductBomMapper extends BaseMapperX { + + default List selectList(Long routeId, Long processId, Long productId) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(MesProRouteProductBomDO::getRouteId, routeId) + .eqIfPresent(MesProRouteProductBomDO::getProcessId, processId) + .eqIfPresent(MesProRouteProductBomDO::getProductId, productId)); + } + + default MesProRouteProductBomDO selectByUnique(Long itemId, Long processId, Long productId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesProRouteProductBomDO::getItemId, itemId) + .eq(MesProRouteProductBomDO::getProcessId, processId) + .eq(MesProRouteProductBomDO::getProductId, productId)); + } + + default void deleteByRouteId(Long routeId) { + delete(new LambdaQueryWrapperX() + .eq(MesProRouteProductBomDO::getRouteId, routeId)); + } + + default void deleteByRouteIdAndProductId(Long routeId, Long productId) { + delete(new LambdaQueryWrapperX() + .eq(MesProRouteProductBomDO::getRouteId, routeId) + .eq(MesProRouteProductBomDO::getProductId, productId)); + } + + default List selectListByRouteIdAndProductId(Long routeId, Long productId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesProRouteProductBomDO::getRouteId, routeId) + .eq(MesProRouteProductBomDO::getProductId, productId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProductMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProductMapper.java new file mode 100644 index 000000000..1afbb832f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/route/MesProRouteProductMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.route; + +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.route.MesProRouteProductDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 工艺路线产品 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProRouteProductMapper extends BaseMapperX { + + default List selectListByRouteId(Long routeId) { + return selectList(MesProRouteProductDO::getRouteId, routeId); + } + + default MesProRouteProductDO selectByItemId(Long itemId) { + return selectOne(MesProRouteProductDO::getItemId, itemId); + } + + default void deleteByRouteId(Long routeId) { + delete(new LambdaQueryWrapperX() + .eq(MesProRouteProductDO::getRouteId, routeId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskIssueMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskIssueMapper.java new file mode 100644 index 000000000..bcedd814d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskIssueMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskIssuePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskIssueDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 生产任务投料 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProTaskIssueMapper extends BaseMapperX { + + default PageResult selectPage(MesProTaskIssuePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesProTaskIssueDO::getTaskId, reqVO.getTaskId()) + .eqIfPresent(MesProTaskIssueDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesProTaskIssueDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesProTaskIssueDO::getSourceDocType, reqVO.getSourceDocType()) + .betweenIfPresent(MesProTaskIssueDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesProTaskIssueDO::getId)); + } + + default List selectListByTaskId(Long taskId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesProTaskIssueDO::getTaskId, taskId) + .orderByDesc(MesProTaskIssueDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java new file mode 100644 index 000000000..ade7495a8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.List; + +/** + * MES 生产任务 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProTaskMapper extends BaseMapperX { + + default PageResult selectPage(MesProTaskPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesProTaskDO::getCode, reqVO.getCode()) + .likeIfPresent(MesProTaskDO::getName, reqVO.getName()) + .eqIfPresent(MesProTaskDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesProTaskDO::getRouteId, reqVO.getRouteId()) + .eqIfPresent(MesProTaskDO::getProcessId, reqVO.getProcessId()) + .eqIfPresent(MesProTaskDO::getWorkstationId, reqVO.getWorkstationId()) + .eqIfPresent(MesProTaskDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesProTaskDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesProTaskDO::getId)); + } + + default List selectListByWorkOrderId(Long workOrderId) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(MesProTaskDO::getWorkOrderId, workOrderId) + .orderByDesc(MesProTaskDO::getId)); + } + + default List selectListByWorkOrderIds(java.util.Collection workOrderIds) { + return selectList(new LambdaQueryWrapperX() + .in(MesProTaskDO::getWorkOrderId, workOrderIds) + .orderByDesc(MesProTaskDO::getId)); + } + + default void updateProducedQuantity(Long id, + BigDecimal incrProducedQuantity, + BigDecimal incrQualifyQuantity, + BigDecimal incrUnqualifyQuantity) { + update(null, new LambdaUpdateWrapper() + .eq(MesProTaskDO::getId, id) + .setSql("produced_quantity = IFNULL(produced_quantity, 0) + " + incrProducedQuantity) + .setSql("qualify_quantity = IFNULL(qualify_quantity, 0) + " + incrQualifyQuantity) + .setSql("unqualify_quantity = IFNULL(unqualify_quantity, 0) + " + incrUnqualifyQuantity)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderBomMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderBomMapper.java new file mode 100644 index 000000000..28f6f60df --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderBomMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 生产工单 BOM Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProWorkOrderBomMapper extends BaseMapperX { + + default PageResult selectPage(MesProWorkOrderBomPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesProWorkOrderBomDO::getWorkOrderId, reqVO.getWorkOrderId()) + .orderByDesc(MesProWorkOrderBomDO::getId)); + } + + default List selectListByWorkOrderId(Long workOrderId) { + return selectList(MesProWorkOrderBomDO::getWorkOrderId, workOrderId); + } + + default void deleteByWorkOrderId(Long workOrderId) { + delete(MesProWorkOrderBomDO::getWorkOrderId, workOrderId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java new file mode 100644 index 000000000..b6f9b0961 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; + +/** + * MES 生产工单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProWorkOrderMapper extends BaseMapperX { + + default PageResult selectPage(MesProWorkOrderPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesProWorkOrderDO::getCode, reqVO.getCode()) + .likeIfPresent(MesProWorkOrderDO::getName, reqVO.getName()) + .eqIfPresent(MesProWorkOrderDO::getType, reqVO.getType()) + .likeIfPresent(MesProWorkOrderDO::getOrderSourceCode, reqVO.getOrderSourceCode()) + .eqIfPresent(MesProWorkOrderDO::getProductId, reqVO.getProductId()) + .eqIfPresent(MesProWorkOrderDO::getClientId, reqVO.getClientId()) + .betweenIfPresent(MesProWorkOrderDO::getRequestDate, reqVO.getRequestDate()) + .orderByDesc(MesProWorkOrderDO::getId)); + } + + default MesProWorkOrderDO selectByCode(String code) { + return selectOne(MesProWorkOrderDO::getCode, code); + } + + default void updateProducedQuantity(Long id, BigDecimal incrQuantityProduced) { + update(null, new LambdaUpdateWrapper() + .eq(MesProWorkOrderDO::getId, id) + .setSql("quantity_produced = IFNULL(quantity_produced, 0) + " + incrQuantityProduced)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workrecord/MesProWorkRecordLogMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workrecord/MesProWorkRecordLogMapper.java new file mode 100644 index 000000000..487736a6a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workrecord/MesProWorkRecordLogMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.workrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordLogDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 上下工记录流水 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProWorkRecordLogMapper extends BaseMapperX { + + default PageResult selectPage(MesProWorkRecordLogPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesProWorkRecordLogDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MesProWorkRecordLogDO::getWorkstationId, reqVO.getWorkstationId()) + .eqIfPresent(MesProWorkRecordLogDO::getType, reqVO.getType()) + .betweenIfPresent(MesProWorkRecordLogDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesProWorkRecordLogDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workrecord/MesProWorkRecordMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workrecord/MesProWorkRecordMapper.java new file mode 100644 index 000000000..43e5bfcab --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workrecord/MesProWorkRecordMapper.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.workrecord; + +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.workrecord.MesProWorkRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 当前绑定状态(快照) Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesProWorkRecordMapper extends BaseMapperX { + + default MesProWorkRecordDO selectByUserId(Long userId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesProWorkRecordDO::getUserId, userId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/defect/MesQcDefectMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/defect/MesQcDefectMapper.java new file mode 100644 index 000000000..1dd7d8f0e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/defect/MesQcDefectMapper.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.defect; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 缺陷类型 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcDefectMapper extends BaseMapperX { + + default PageResult selectPage(MesQcDefectPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesQcDefectDO::getCode, reqVO.getCode()) + .likeIfPresent(MesQcDefectDO::getName, reqVO.getName()) + .eqIfPresent(MesQcDefectDO::getType, reqVO.getType()) + .eqIfPresent(MesQcDefectDO::getLevel, reqVO.getLevel()) + .orderByDesc(MesQcDefectDO::getId)); + } + + default MesQcDefectDO selectByCode(String code) { + return selectOne(MesQcDefectDO::getCode, code); + } + + default MesQcDefectDO selectByName(String name) { + return selectOne(MesQcDefectDO::getName, name); + } + + default List selectList() { + return selectList(new LambdaQueryWrapperX() + .orderByDesc(MesQcDefectDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/defectrecord/MesQcDefectRecordMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/defectrecord/MesQcDefectRecordMapper.java new file mode 100644 index 000000000..0b93d6d52 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/defectrecord/MesQcDefectRecordMapper.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.defectrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo.MesQcDefectRecordPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 质检缺陷记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcDefectRecordMapper extends BaseMapperX { + + default PageResult selectPage(MesQcDefectRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesQcDefectRecordDO::getQcType, reqVO.getQcType()) + .eqIfPresent(MesQcDefectRecordDO::getQcId, reqVO.getQcId()) + .eqIfPresent(MesQcDefectRecordDO::getLineId, reqVO.getLineId()) + .orderByDesc(MesQcDefectRecordDO::getId)); + } + + default List selectListByQcTypeAndQcId(Integer qcType, Long qcId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesQcDefectRecordDO::getQcType, qcType) + .eq(MesQcDefectRecordDO::getQcId, qcId)); + } + + default void deleteByQcTypeAndQcId(Integer qcType, Long qcId) { + delete(new LambdaQueryWrapperX() + .eq(MesQcDefectRecordDO::getQcType, qcType) + .eq(MesQcDefectRecordDO::getQcId, qcId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicator/MesQcIndicatorMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicator/MesQcIndicatorMapper.java new file mode 100644 index 000000000..b13f2f24a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicator/MesQcIndicatorMapper.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.indicator; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo.MesQcIndicatorPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 质检指标 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcIndicatorMapper extends BaseMapperX { + + default PageResult selectPage(MesQcIndicatorPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesQcIndicatorDO::getCode, reqVO.getCode()) + .likeIfPresent(MesQcIndicatorDO::getName, reqVO.getName()) + .eqIfPresent(MesQcIndicatorDO::getType, reqVO.getType()) + .eqIfPresent(MesQcIndicatorDO::getResultType, reqVO.getResultType()) + .orderByDesc(MesQcIndicatorDO::getId)); + } + + default MesQcIndicatorDO selectByCode(String code) { + return selectOne(MesQcIndicatorDO::getCode, code); + } + + default MesQcIndicatorDO selectByName(String name) { + return selectOne(MesQcIndicatorDO::getName, name); + } + + default List selectList() { + return selectList(new LambdaQueryWrapperX() + .orderByDesc(MesQcIndicatorDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultDetailMapper.java new file mode 100644 index 000000000..b11de0f46 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultDetailMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult; + +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.qc.indicatorresult.MesQcIndicatorResultDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 检验结果明细记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcIndicatorResultDetailMapper extends BaseMapperX { + + default List selectListByResultId(Long resultId) { + return selectList(MesQcIndicatorResultDetailDO::getResultId, resultId); + } + + default void deleteByResultId(Long resultId) { + delete(new LambdaQueryWrapperX() + .eq(MesQcIndicatorResultDetailDO::getResultId, resultId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultMapper.java new file mode 100644 index 000000000..265ba1218 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultMapper.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 检验结果记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcIndicatorResultMapper extends BaseMapperX { + + default PageResult selectPage(MesQcIndicatorResultPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesQcIndicatorResultDO::getQcId, reqVO.getQcId()) + .eqIfPresent(MesQcIndicatorResultDO::getQcType, reqVO.getQcType()) + .likeIfPresent(MesQcIndicatorResultDO::getCode, reqVO.getCode()) + .eqIfPresent(MesQcIndicatorResultDO::getItemId, reqVO.getItemId()) + .orderByDesc(MesQcIndicatorResultDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcLineMapper.java new file mode 100644 index 000000000..4dad4b940 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcLineMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 过程检验单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcIpqcLineMapper extends BaseMapperX { + + default PageResult selectPage(MesQcIpqcLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesQcIpqcLineDO::getIpqcId, reqVO.getIpqcId()) + .orderByAsc(MesQcIpqcLineDO::getId)); + } + + default List selectListByIpqcId(Long ipqcId) { + return selectList(MesQcIpqcLineDO::getIpqcId, ipqcId); + } + + default void deleteByIpqcId(Long ipqcId) { + delete(new LambdaQueryWrapperX() + .eq(MesQcIpqcLineDO::getIpqcId, ipqcId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java new file mode 100644 index 000000000..2a7bc213a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 过程检验单(IPQC) Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcIpqcMapper extends BaseMapperX { + + default PageResult selectPage(MesQcIpqcPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesQcIpqcDO::getCode, reqVO.getCode()) + .eqIfPresent(MesQcIpqcDO::getType, reqVO.getType()) + .eqIfPresent(MesQcIpqcDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesQcIpqcDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesQcIpqcDO::getCheckResult, reqVO.getCheckResult()) + .eqIfPresent(MesQcIpqcDO::getStatus, reqVO.getStatus()) + .eqIfPresent(MesQcIpqcDO::getInspectorUserId, reqVO.getInspectorUserId()) + .orderByDesc(MesQcIpqcDO::getId)); + } + + default MesQcIpqcDO selectByCode(String code) { + return selectOne(MesQcIpqcDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcLineMapper.java new file mode 100644 index 000000000..d238845c1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcLineMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.iqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 来料检验单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcIqcLineMapper extends BaseMapperX { + + default PageResult selectPage(MesQcIqcLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesQcIqcLineDO::getIqcId, reqVO.getIqcId()) + .orderByAsc(MesQcIqcLineDO::getId)); + } + + default List selectListByIqcId(Long iqcId) { + return selectList(MesQcIqcLineDO::getIqcId, iqcId); + } + + default void deleteByIqcId(Long iqcId) { + delete(new LambdaQueryWrapperX() + .eq(MesQcIqcLineDO::getIqcId, iqcId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcMapper.java new file mode 100644 index 000000000..50a50e91a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.iqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 来料检验单(IQC) Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcIqcMapper extends BaseMapperX { + + default PageResult selectPage(MesQcIqcPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesQcIqcDO::getCode, reqVO.getCode()) + .eqIfPresent(MesQcIqcDO::getVendorId, reqVO.getVendorId()) + .likeIfPresent(MesQcIqcDO::getVendorBatch, reqVO.getVendorBatch()) + .eqIfPresent(MesQcIqcDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesQcIqcDO::getCheckResult, reqVO.getCheckResult()) + .betweenIfPresent(MesQcIqcDO::getReceiveDate, reqVO.getReceiveDate()) + .betweenIfPresent(MesQcIqcDO::getInspectDate, reqVO.getInspectDate()) + .eqIfPresent(MesQcIqcDO::getInspectorUserId, reqVO.getInspectorUserId()) + .orderByDesc(MesQcIqcDO::getId)); + } + + default MesQcIqcDO selectByCode(String code) { + return selectOne(MesQcIqcDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcLineMapper.java new file mode 100644 index 000000000..34031d0c7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcLineMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.line.MesQcOqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 出货检验单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcOqcLineMapper extends BaseMapperX { + + default PageResult selectPage(MesQcOqcLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesQcOqcLineDO::getOqcId, reqVO.getOqcId()) + .orderByAsc(MesQcOqcLineDO::getId)); + } + + default List selectListByOqcId(Long oqcId) { + return selectList(MesQcOqcLineDO::getOqcId, oqcId); + } + + default void deleteByOqcId(Long oqcId) { + delete(new LambdaQueryWrapperX() + .eq(MesQcOqcLineDO::getOqcId, oqcId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java new file mode 100644 index 000000000..26258189c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 出货检验单(OQC) Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcOqcMapper extends BaseMapperX { + + default PageResult selectPage(MesQcOqcPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesQcOqcDO::getCode, reqVO.getCode()) + .eqIfPresent(MesQcOqcDO::getClientId, reqVO.getClientId()) + .likeIfPresent(MesQcOqcDO::getBatchCode, reqVO.getBatchCode()) + .eqIfPresent(MesQcOqcDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesQcOqcDO::getCheckResult, reqVO.getCheckResult()) + .orderByDesc(MesQcOqcDO::getId)); + } + + default MesQcOqcDO selectByCode(String code) { + return selectOne(MesQcOqcDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/pendinginspect/MesQcPendingInspectMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/pendinginspect/MesQcPendingInspectMapper.java new file mode 100644 index 000000000..6f8b78f7f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/pendinginspect/MesQcPendingInspectMapper.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.pendinginspect; + +import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectRespVO; +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * MES 待检任务 Mapper + * + * 使用 UNION ALL SQL 从多个来源表(到货通知单、外协入库单等)查询待检行 + */ +@Mapper +public interface MesQcPendingInspectMapper { + + IPage selectQcPendingPage(IPage page, + @Param("sourceDocCode") String sourceDocCode, + @Param("qcType") Integer qcType, + @Param("itemId") Long itemId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcLineMapper.java new file mode 100644 index 000000000..1fc134dfc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcLineMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.line.MesQcRqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 退货检验行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcRqcLineMapper extends BaseMapperX { + + default PageResult selectPage(MesQcRqcLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesQcRqcLineDO::getRqcId, reqVO.getRqcId()) + .orderByAsc(MesQcRqcLineDO::getId)); + } + + default List selectListByRqcId(Long rqcId) { + return selectList(MesQcRqcLineDO::getRqcId, rqcId); + } + + default void deleteByRqcId(Long rqcId) { + delete(new LambdaQueryWrapperX() + .eq(MesQcRqcLineDO::getRqcId, rqcId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcMapper.java new file mode 100644 index 000000000..0874ea8d4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.MesQcRqcPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 退货检验单(RQC) Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcRqcMapper extends BaseMapperX { + + default PageResult selectPage(MesQcRqcPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesQcRqcDO::getCode, reqVO.getCode()) + .eqIfPresent(MesQcRqcDO::getSourceDocType, reqVO.getSourceDocType()) + .likeIfPresent(MesQcRqcDO::getSourceDocCode, reqVO.getSourceDocCode()) + .eqIfPresent(MesQcRqcDO::getItemId, reqVO.getItemId()) + .likeIfPresent(MesQcRqcDO::getBatchCode, reqVO.getBatchCode()) + .eqIfPresent(MesQcRqcDO::getCheckResult, reqVO.getCheckResult()) + .eqIfPresent(MesQcRqcDO::getStatus, reqVO.getStatus()) + .eqIfPresent(MesQcRqcDO::getInspectorUserId, reqVO.getInspectorUserId()) + .orderByDesc(MesQcRqcDO::getId)); + } + + default MesQcRqcDO selectByCode(String code) { + return selectOne(MesQcRqcDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateIndicatorMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateIndicatorMapper.java new file mode 100644 index 000000000..94b2ae2e1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateIndicatorMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.template; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.MesQcTemplateIndicatorPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 质检方案-检测指标项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcTemplateIndicatorMapper extends BaseMapperX { + + default PageResult selectPage(MesQcTemplateIndicatorPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesQcTemplateIndicatorDO::getTemplateId, reqVO.getTemplateId()) + .orderByAsc(MesQcTemplateIndicatorDO::getId)); + } + + default List selectListByTemplateId(Long templateId) { + return selectList(MesQcTemplateIndicatorDO::getTemplateId, templateId); + } + + default void deleteByTemplateId(Long templateId) { + delete(new LambdaQueryWrapperX() + .eq(MesQcTemplateIndicatorDO::getTemplateId, templateId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateItemMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateItemMapper.java new file mode 100644 index 000000000..2e3b676fd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateItemMapper.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.template; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item.MesQcTemplateItemPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 质检方案-产品关联 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcTemplateItemMapper extends BaseMapperX { + + default PageResult selectPage(MesQcTemplateItemPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesQcTemplateItemDO::getTemplateId, reqVO.getTemplateId()) + .orderByAsc(MesQcTemplateItemDO::getId)); + } + + default List selectListByTemplateId(Long templateId) { + return selectList(MesQcTemplateItemDO::getTemplateId, templateId); + } + + default List selectListByItemId(Long itemId) { + return selectList(MesQcTemplateItemDO::getItemId, itemId); + } + + default MesQcTemplateItemDO selectByTemplateIdAndItemId(Long templateId, Long itemId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesQcTemplateItemDO::getTemplateId, templateId) + .eq(MesQcTemplateItemDO::getItemId, itemId)); + } + + default void deleteByTemplateId(Long templateId) { + delete(new LambdaQueryWrapperX() + .eq(MesQcTemplateItemDO::getTemplateId, templateId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateMapper.java new file mode 100644 index 000000000..29242fe30 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateMapper.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.qc.template; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplatePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 质检方案 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesQcTemplateMapper extends BaseMapperX { + + default PageResult selectPage(MesQcTemplatePageReqVO reqVO) { + LambdaQueryWrapperX query = new LambdaQueryWrapperX() + .likeIfPresent(MesQcTemplateDO::getCode, reqVO.getCode()) + .likeIfPresent(MesQcTemplateDO::getName, reqVO.getName()) + .orderByDesc(MesQcTemplateDO::getId); + if (reqVO.getType() != null) { + query.apply(MyBatisUtils.findInSet("types", reqVO.getType())); + } + query.eqIfPresent(MesQcTemplateDO::getStatus, reqVO.getStatus()); + return selectPage(reqVO, query); + } + + default MesQcTemplateDO selectByCode(String code) { + return selectOne(MesQcTemplateDO::getCode, code); + } + + default List selectList() { + return selectList(new LambdaQueryWrapperX() + .orderByDesc(MesQcTemplateDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolMapper.java new file mode 100644 index 000000000..f2f256b59 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.tm.tool; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.MesTmToolPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 工具台账 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesTmToolMapper extends BaseMapperX { + + default PageResult selectPage(MesTmToolPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesTmToolDO::getCode, reqVO.getCode()) + .likeIfPresent(MesTmToolDO::getName, reqVO.getName()) + .eqIfPresent(MesTmToolDO::getToolTypeId, reqVO.getToolTypeId()) + .likeIfPresent(MesTmToolDO::getBrand, reqVO.getBrand()) + .likeIfPresent(MesTmToolDO::getSpec, reqVO.getSpec()) + .eqIfPresent(MesTmToolDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesTmToolDO::getId)); + } + + default MesTmToolDO selectByCode(String code) { + return selectOne(MesTmToolDO::getCode, code); + } + + default Long selectCountByToolTypeId(Long toolTypeId) { + return selectCount(MesTmToolDO::getToolTypeId, toolTypeId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolTypeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolTypeMapper.java new file mode 100644 index 000000000..4af70a55a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolTypeMapper.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.tm.tool; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolTypeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 工具类型 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesTmToolTypeMapper extends BaseMapperX { + + default PageResult selectPage(MesTmToolTypePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesTmToolTypeDO::getCode, reqVO.getCode()) + .likeIfPresent(MesTmToolTypeDO::getName, reqVO.getName()) + .eqIfPresent(MesTmToolTypeDO::getMaintenType, reqVO.getMaintenType()) + .orderByDesc(MesTmToolTypeDO::getId)); + } + + default MesTmToolTypeDO selectByCode(String code) { + return selectOne(MesTmToolTypeDO::getCode, code); + } + + default MesTmToolTypeDO selectByName(String name) { + return selectOne(MesTmToolTypeDO::getName, name); + } + + default List selectList() { + return selectList(new LambdaQueryWrapperX() + .orderByDesc(MesTmToolTypeDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeLineMapper.java new file mode 100644 index 000000000..5ac266f90 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeLineMapper.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 到货通知单行 Mapper + */ +@Mapper +public interface MesWmArrivalNoticeLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmArrivalNoticeLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmArrivalNoticeLineDO::getNoticeId, reqVO.getNoticeId()) + .orderByDesc(MesWmArrivalNoticeLineDO::getId)); + } + + default List selectListByNoticeId(Long noticeId) { + return selectList(MesWmArrivalNoticeLineDO::getNoticeId, noticeId); + } + + default void deleteByNoticeId(Long noticeId) { + delete(MesWmArrivalNoticeLineDO::getNoticeId, noticeId); + } + + default List selectListByIqcPending(List noticeIds) { + return selectList(new LambdaQueryWrapperX() + .in(MesWmArrivalNoticeLineDO::getNoticeId, noticeIds) + .eq(MesWmArrivalNoticeLineDO::getIqcCheckFlag, true) + .isNull(MesWmArrivalNoticeLineDO::getIqcId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeMapper.java new file mode 100644 index 000000000..38119a9ec --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeMapper.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 到货通知单 Mapper + */ +@Mapper +public interface MesWmArrivalNoticeMapper extends BaseMapperX { + + default PageResult selectPage(MesWmArrivalNoticePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmArrivalNoticeDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmArrivalNoticeDO::getName, reqVO.getName()) + .likeIfPresent(MesWmArrivalNoticeDO::getPurchaseOrderCode, reqVO.getPurchaseOrderCode()) + .eqIfPresent(MesWmArrivalNoticeDO::getVendorId, reqVO.getVendorId()) + .betweenIfPresent(MesWmArrivalNoticeDO::getArrivalDate, reqVO.getArrivalDate()) + .eqIfPresent(MesWmArrivalNoticeDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesWmArrivalNoticeDO::getId)); + } + + default MesWmArrivalNoticeDO selectByCode(String code) { + return selectOne(MesWmArrivalNoticeDO::getCode, code); + } + + default List selectListByStatus(Integer status) { + return selectList(MesWmArrivalNoticeDO::getStatus, status); + } + + default Long selectCountByVendorId(Long vendorId) { + return selectCount(MesWmArrivalNoticeDO::getVendorId, vendorId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/barcode/MesWmBarcodeConfigMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/barcode/MesWmBarcodeConfigMapper.java new file mode 100644 index 000000000..d716f9454 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/barcode/MesWmBarcodeConfigMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.barcode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config.MesWmBarcodeConfigPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeConfigDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 条码配置 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmBarcodeConfigMapper extends BaseMapperX { + + default PageResult selectPage(MesWmBarcodeConfigPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmBarcodeConfigDO::getFormat, reqVO.getFormat()) + .eqIfPresent(MesWmBarcodeConfigDO::getBizType, reqVO.getBizType()) + .eqIfPresent(MesWmBarcodeConfigDO::getAutoGenerateFlag, reqVO.getAutoGenerateFlag()) + .eqIfPresent(MesWmBarcodeConfigDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesWmBarcodeConfigDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesWmBarcodeConfigDO::getId)); + } + + default MesWmBarcodeConfigDO selectByBizType(Integer bizType) { + return selectOne(MesWmBarcodeConfigDO::getBizType, bizType); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/barcode/MesWmBarcodeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/barcode/MesWmBarcodeMapper.java new file mode 100644 index 000000000..d36191227 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/barcode/MesWmBarcodeMapper.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.barcode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 条码清单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmBarcodeMapper extends BaseMapperX { + + default PageResult selectPage(MesWmBarcodePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmBarcodeDO::getConfigId, reqVO.getConfigId()) + .eqIfPresent(MesWmBarcodeDO::getFormat, reqVO.getFormat()) + .eqIfPresent(MesWmBarcodeDO::getBizType, reqVO.getBizType()) + .likeIfPresent(MesWmBarcodeDO::getContent, reqVO.getContent()) + .eqIfPresent(MesWmBarcodeDO::getBizId, reqVO.getBizId()) + .likeIfPresent(MesWmBarcodeDO::getBizCode, reqVO.getBizCode()) + .likeIfPresent(MesWmBarcodeDO::getBizName, reqVO.getBizName()) + .eqIfPresent(MesWmBarcodeDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesWmBarcodeDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesWmBarcodeDO::getId)); + } + + default MesWmBarcodeDO selectByBizTypeAndBizId(Integer bizType, Long bizId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmBarcodeDO::getBizType, bizType) + .eq(MesWmBarcodeDO::getBizId, bizId)); + } + + default MesWmBarcodeDO selectByContent(String content) { + return selectOne(MesWmBarcodeDO::getContent, content); + } + + default Long selectCountByConfigId(Long configId) { + return selectCount(MesWmBarcodeDO::getConfigId, configId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java new file mode 100644 index 000000000..195858cc8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java @@ -0,0 +1,152 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.batch; + + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 批次管理 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmBatchMapper extends BaseMapperX { + + default MesWmBatchDO selectByCode(String code) { + return selectOne(MesWmBatchDO:: getCode, code); + } + + default PageResult selectPage(MesWmBatchPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmBatchDO::getCode, reqVO.getCode()) + .eqIfPresent(MesWmBatchDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesWmBatchDO::getVendorId, reqVO.getVendorId()) + .eqIfPresent(MesWmBatchDO::getClientId, reqVO.getClientId()) + .likeIfPresent(MesWmBatchDO::getSalesOrderCode, reqVO.getSalesOrderCode()) + .likeIfPresent(MesWmBatchDO::getPurchaseOrderCode, reqVO.getPurchaseOrderCode()) + .eqIfPresent(MesWmBatchDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesWmBatchDO::getTaskId, reqVO.getTaskId()) + .eqIfPresent(MesWmBatchDO::getWorkstationId, reqVO.getWorkstationId()) + .eqIfPresent(MesWmBatchDO::getToolId, reqVO.getToolId()) + .eqIfPresent(MesWmBatchDO::getMoldId, reqVO.getMoldId()) + .likeIfPresent(MesWmBatchDO::getLotNumber, reqVO.getLotNumber()) + .eqIfPresent(MesWmBatchDO::getQualityStatus, reqVO.getQualityStatus()) + .betweenIfPresent(MesWmBatchDO::getProduceDate, reqVO.getProduceDate()) + .betweenIfPresent(MesWmBatchDO::getExpireDate, reqVO.getExpireDate()) + .betweenIfPresent(MesWmBatchDO::getReceiptDate, reqVO.getReceiptDate()) + .orderByDesc(MesWmBatchDO::getId)); + } + + /** + * 根据参数查询匹配的第一条批次记录 + *

+ * 使用 NULL 值精确匹配,返回 ID 最小的批次 + * + * @param batch 批次参数 + * @return 匹配的批次记录 + */ + default MesWmBatchDO selectFirst(MesWmBatchDO batch) { + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.eq(MesWmBatchDO::getItemId, batch.getItemId()); + if (ObjUtil.isNull(batch.getVendorId())) { + query.isNull(MesWmBatchDO::getVendorId); + } else { + query.eq(MesWmBatchDO::getVendorId, batch.getVendorId()); + } + if (ObjUtil.isNull(batch.getClientId())) { + query.isNull(MesWmBatchDO::getClientId); + } else { + query.eq(MesWmBatchDO::getClientId, batch.getClientId()); + } + if (ObjUtil.isNull(batch.getSalesOrderCode())) { + query.isNull(MesWmBatchDO::getSalesOrderCode); + } else { + query.eq(MesWmBatchDO::getSalesOrderCode, batch.getSalesOrderCode()); + } + if (ObjUtil.isNull(batch.getPurchaseOrderCode())) { + query.isNull(MesWmBatchDO::getPurchaseOrderCode); + } else { + query.eq(MesWmBatchDO::getPurchaseOrderCode, batch.getPurchaseOrderCode()); + } + if (ObjUtil.isNull(batch.getWorkOrderId())) { + query.isNull(MesWmBatchDO::getWorkOrderId); + } else { + query.eq(MesWmBatchDO::getWorkOrderId, batch.getWorkOrderId()); + } + if (ObjUtil.isNull(batch.getTaskId())) { + query.isNull(MesWmBatchDO::getTaskId); + } else { + query.eq(MesWmBatchDO::getTaskId, batch.getTaskId()); + } + if (ObjUtil.isNull(batch.getWorkstationId())) { + query.isNull(MesWmBatchDO::getWorkstationId); + } else { + query.eq(MesWmBatchDO::getWorkstationId, batch.getWorkstationId()); + } + if (ObjUtil.isNull(batch.getToolId())) { + query.isNull(MesWmBatchDO::getToolId); + } else { + query.eq(MesWmBatchDO::getToolId, batch.getToolId()); + } + if (ObjUtil.isNull(batch.getMoldId())) { + query.isNull(MesWmBatchDO::getMoldId); + } else { + query.eq(MesWmBatchDO::getMoldId, batch.getMoldId()); + } + if (ObjUtil.isNull(batch.getLotNumber())) { + query.isNull(MesWmBatchDO::getLotNumber); + } else { + query.eq(MesWmBatchDO::getLotNumber, batch.getLotNumber()); + } + if (ObjUtil.isNull(batch.getQualityStatus())) { + query.isNull(MesWmBatchDO::getQualityStatus); + } else { + query.eq(MesWmBatchDO::getQualityStatus, batch.getQualityStatus()); + } + if (ObjUtil.isNull(batch.getProduceDate())) { + query.isNull(MesWmBatchDO::getProduceDate); + } else { + query.eq(MesWmBatchDO::getProduceDate, batch.getProduceDate()); + } + if (ObjUtil.isNull(batch.getExpireDate())) { + query.isNull(MesWmBatchDO::getExpireDate); + } else { + query.eq(MesWmBatchDO::getExpireDate, batch.getExpireDate()); + } + if (ObjUtil.isNull(batch.getReceiptDate())) { + query.isNull(MesWmBatchDO::getReceiptDate); + } else { + query.eq(MesWmBatchDO::getReceiptDate, batch.getReceiptDate()); + } + + // 返回 ID 最小的批次 + query.orderByAsc(MesWmBatchDO::getId); + query.last("LIMIT 1"); + return selectOne(query); + } + + /** + * 查询向前追溯批次列表 + *

+ * 查询当前批次被哪些工单的哪些批次产品消耗 + * SQL 逻辑:从领料明细 -> 领料单 -> 报工记录 -> 生产入库单 -> 生产入库行 + */ + List selectListByForward(String batchCode); + + /** + * 查询向后追溯批次列表 + *

+ * 查询当前批次的产品使用了哪些批次的物资 + * SQL 逻辑:从生产入库明细 -> 生产入库单 -> 领料单 -> 领料明细 + */ + List selectListByBackward(String batchCode); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeDetailMapper.java new file mode 100644 index 000000000..f9bf8bff0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeDetailMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 物料消耗记录明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmItemConsumeDetailMapper extends BaseMapperX { + + default List selectListByConsumeId(Long consumeId) { + return selectList(MesWmItemConsumeDetailDO::getConsumeId, consumeId); + } + + default List selectListByLineId(Long lineId) { + return selectList(MesWmItemConsumeDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeLineMapper.java new file mode 100644 index 000000000..722c63db2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeLineMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume.vo.MesWmItemConsumeLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 物料消耗记录行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmItemConsumeLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmItemConsumeLinePageReqVO reqVO, + Long consumeId) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(MesWmItemConsumeLineDO::getConsumeId, consumeId) + .orderByDesc(MesWmItemConsumeLineDO::getId)); + } + + default List selectListByConsumeId(Long consumeId) { + return selectList(MesWmItemConsumeLineDO::getConsumeId, consumeId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeMapper.java new file mode 100644 index 000000000..1a8832dd3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemconsume/MesWmItemConsumeMapper.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 物料消耗记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmItemConsumeMapper extends BaseMapperX { + + default MesWmItemConsumeDO selectByFeedbackId(Long feedbackId) { + return selectOne(MesWmItemConsumeDO::getFeedbackId, feedbackId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptDetailMapper.java new file mode 100644 index 000000000..0771f1bd8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptDetailMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 采购入库明细 Mapper + */ +@Mapper +public interface MesWmItemReceiptDetailMapper extends BaseMapperX { + + default List selectListByReceiptId(Long receiptId) { + return selectList(MesWmItemReceiptDetailDO::getReceiptId, receiptId); + } + + default List selectListByLineId(Long lineId) { + return selectList(MesWmItemReceiptDetailDO::getLineId, lineId); + } + + default void deleteByReceiptId(Long receiptId) { + delete(MesWmItemReceiptDetailDO::getReceiptId, receiptId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmItemReceiptDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptLineMapper.java new file mode 100644 index 000000000..6499b9adf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptLineMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 采购入库单行 Mapper + */ +@Mapper +public interface MesWmItemReceiptLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmItemReceiptLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmItemReceiptLineDO::getReceiptId, reqVO.getReceiptId()) + .inIfPresent(MesWmItemReceiptLineDO::getReceiptId, reqVO.getReceiptIds()) + .orderByDesc(MesWmItemReceiptLineDO::getId)); + } + + default List selectListByReceiptId(Long receiptId) { + return selectList(MesWmItemReceiptLineDO::getReceiptId, receiptId); + } + + default void deleteByReceiptId(Long receiptId) { + delete(MesWmItemReceiptLineDO::getReceiptId, receiptId); + } + + default List selectListByReceiptIds(java.util.Collection receiptIds) { + return selectList(MesWmItemReceiptLineDO::getReceiptId, receiptIds); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptMapper.java new file mode 100644 index 000000000..486cee3f8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/itemreceipt/MesWmItemReceiptMapper.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 采购入库单 Mapper + */ +@Mapper +public interface MesWmItemReceiptMapper extends BaseMapperX { + + default PageResult selectPage(MesWmItemReceiptPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmItemReceiptDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmItemReceiptDO::getName, reqVO.getName()) + .eqIfPresent(MesWmItemReceiptDO::getVendorId, reqVO.getVendorId()) + .betweenIfPresent(MesWmItemReceiptDO::getReceiptDate, reqVO.getReceiptDate()) + .orderByDesc(MesWmItemReceiptDO::getId)); + } + + default MesWmItemReceiptDO selectByCode(String code) { + return selectOne(MesWmItemReceiptDO::getCode, code); + } + + default Long selectCountByVendorId(Long vendorId) { + return selectCount(MesWmItemReceiptDO::getVendorId, vendorId); + } + + default List selectListByVendorId(Long vendorId) { + return selectList(MesWmItemReceiptDO::getVendorId, vendorId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/materialstock/MesWmMaterialStockMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/materialstock/MesWmMaterialStockMapper.java new file mode 100644 index 000000000..178717cbe --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/materialstock/MesWmMaterialStockMapper.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; + +/** + * MES 库存台账 Mapper + */ +@Mapper +public interface MesWmMaterialStockMapper extends BaseMapperX { + + default PageResult selectPage(MesWmMaterialStockPageReqVO reqVO, + Collection itemTypeIds, + Collection itemIds) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .inIfPresent(MesWmMaterialStockDO::getItemTypeId, itemTypeIds) + .inIfPresent(MesWmMaterialStockDO::getItemId, itemIds) + .likeIfPresent(MesWmMaterialStockDO::getBatchCode, reqVO.getBatchCode()) + .eqIfPresent(MesWmMaterialStockDO::getWarehouseId, reqVO.getWarehouseId()) + .eqIfPresent(MesWmMaterialStockDO::getLocationId, reqVO.getLocationId()) + .eqIfPresent(MesWmMaterialStockDO::getAreaId, reqVO.getAreaId()) + .eqIfPresent(MesWmMaterialStockDO::getVendorId, reqVO.getVendorId()) + .eqIfPresent(MesWmMaterialStockDO::getFrozen, reqVO.getFrozen()) + .ne(MesWmMaterialStockDO::getQuantity, BigDecimal.ZERO) + .orderByAsc(MesWmMaterialStockDO::getReceiptTime)); + } + + default Long selectCountByWarehouseId(Long warehouseId) { + return selectCount(MesWmMaterialStockDO::getWarehouseId, warehouseId); + } + + default Long selectCountByLocationId(Long locationId) { + return selectCount(MesWmMaterialStockDO::getLocationId, locationId); + } + + default Long selectCountByAreaId(Long areaId) { + return selectCount(MesWmMaterialStockDO::getAreaId, areaId); + } + + default List selectListByIds(Collection ids) { + return selectByIds(ids); + } + + default void updateByIds(Collection ids, MesWmMaterialStockDO updateObj) { + update(updateObj, new LambdaUpdateWrapper() + .in(MesWmMaterialStockDO::getId, ids)); + } + + /** + * 增量更新库存数量 + * + * @param id 库存记录编号 + * @param count 变动数量(正数=增加,负数=扣减) + * @param checkFlag 是否校验库存充足(为 true 时扣减不允许变为负数) + * @return 影响行数 + */ + default int updateQuantity(Long id, BigDecimal count, boolean checkFlag) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() + .eq(MesWmMaterialStockDO::getId, id) + .setSql("quantity = quantity + " + count); + if (checkFlag && count.compareTo(BigDecimal.ZERO) < 0) { + updateWrapper.ge(MesWmMaterialStockDO::getQuantity, count.abs()); // CAS 防负库存 + } + return update(null, updateWrapper); + } + + default MesWmMaterialStockDO selectByCompositeKey(Long itemId, Long warehouseId, Long locationId, + Long areaId, Long batchId) { + LambdaQueryWrapperX wrapper = new LambdaQueryWrapperX() + .eqIfPresent(MesWmMaterialStockDO::getItemId, itemId) + .eqIfPresent(MesWmMaterialStockDO::getWarehouseId, warehouseId) + .eqIfPresent(MesWmMaterialStockDO::getLocationId, locationId) + .eqIfPresent(MesWmMaterialStockDO::getAreaId, areaId); + // batchId=null 时精确匹配 is null,避免 eqIfPresent 跳过条件导致匹配到其他批次 + if (batchId != null) { + wrapper.eq(MesWmMaterialStockDO::getBatchId, batchId); + } else { + wrapper.isNull(MesWmMaterialStockDO::getBatchId); + } + return selectOne(wrapper); + } + + default List selectList(MesWmMaterialStockListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(MesWmMaterialStockDO::getWarehouseId, reqVO.getWarehouseId()) + .eqIfPresent(MesWmMaterialStockDO::getLocationId, reqVO.getLocationId()) + .eqIfPresent(MesWmMaterialStockDO::getAreaId, reqVO.getAreaId()) + .eqIfPresent(MesWmMaterialStockDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesWmMaterialStockDO::getBatchId, reqVO.getBatchId()) + .likeIfPresent(MesWmMaterialStockDO::getBatchCode, reqVO.getBatchCode()) + .geIfPresent(MesWmMaterialStockDO::getUpdateTime, reqVO.getStartTime()) + .leIfPresent(MesWmMaterialStockDO::getUpdateTime, reqVO.getEndTime()) + .ne(MesWmMaterialStockDO::getQuantity, BigDecimal.ZERO) + .orderByAsc(MesWmMaterialStockDO::getReceiptTime)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueDetailMapper.java new file mode 100644 index 000000000..68ad92987 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueDetailMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 杂项出库明细 Mapper + */ +@Mapper +public interface MesWmMiscIssueDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(MesWmMiscIssueDetailDO::getLineId, lineId); + } + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmMiscIssueDetailDO::getIssueId, issueId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmMiscIssueDetailDO::getIssueId, issueId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmMiscIssueDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueLineMapper.java new file mode 100644 index 000000000..3f6d99faa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueLineMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 杂项出库单行 Mapper + */ +@Mapper +public interface MesWmMiscIssueLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmMiscIssueLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmMiscIssueLineDO::getIssueId, reqVO.getIssueId()) + .orderByDesc(MesWmMiscIssueLineDO::getId)); + } + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmMiscIssueLineDO::getIssueId, issueId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmMiscIssueLineDO::getIssueId, issueId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueMapper.java new file mode 100644 index 000000000..f5b44400d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscissue/MesWmMiscIssueMapper.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssuePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 杂项出库单 Mapper + */ +@Mapper +public interface MesWmMiscIssueMapper extends BaseMapperX { + + default PageResult selectPage(MesWmMiscIssuePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmMiscIssueDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmMiscIssueDO::getName, reqVO.getName()) + .eqIfPresent(MesWmMiscIssueDO::getType, reqVO.getType()) + .likeIfPresent(MesWmMiscIssueDO::getSourceDocCode, reqVO.getSourceDocCode()) + .eqIfPresent(MesWmMiscIssueDO::getSourceDocType, reqVO.getSourceDocType()) + .eqIfPresent(MesWmMiscIssueDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesWmMiscIssueDO::getIssueDate, reqVO.getIssueDate()) + .orderByDesc(MesWmMiscIssueDO::getId)); + } + + default MesWmMiscIssueDO selectByCode(String code) { + return selectOne(MesWmMiscIssueDO::getCode, code); + } + + default List selectListByStatus(Integer status) { + return selectList(MesWmMiscIssueDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptDetailMapper.java new file mode 100644 index 000000000..f02cfe015 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptDetailMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 杂项入库明细 Mapper + */ +@Mapper +public interface MesWmMiscReceiptDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(MesWmMiscReceiptDetailDO::getLineId, lineId); + } + + default List selectListByReceiptId(Long receiptId) { + return selectList(MesWmMiscReceiptDetailDO::getReceiptId, receiptId); + } + + default void deleteByReceiptId(Long receiptId) { + delete(MesWmMiscReceiptDetailDO::getReceiptId, receiptId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmMiscReceiptDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptLineMapper.java new file mode 100644 index 000000000..88994e919 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptLineMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 杂项入库单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmMiscReceiptLineMapper extends BaseMapperX { + + default List selectListByReceiptId(Long receiptId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmMiscReceiptLineDO::getReceiptId, receiptId) + .orderByAsc(MesWmMiscReceiptLineDO::getId)); + } + + default int deleteByReceiptId(Long receiptId) { + return delete(new LambdaQueryWrapperX() + .eq(MesWmMiscReceiptLineDO::getReceiptId, receiptId)); + } + + default PageResult selectPage(MesWmMiscReceiptLinePageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eq(MesWmMiscReceiptLineDO::getReceiptId, pageReqVO.getReceiptId()) + .orderByAsc(MesWmMiscReceiptLineDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptMapper.java new file mode 100644 index 000000000..abbdc05c7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/miscreceipt/MesWmMiscReceiptMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.MesWmMiscReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 杂项入库单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmMiscReceiptMapper extends BaseMapperX { + + default PageResult selectPage(MesWmMiscReceiptPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmMiscReceiptDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmMiscReceiptDO::getName, reqVO.getName()) + .eqIfPresent(MesWmMiscReceiptDO::getType, reqVO.getType()) + .likeIfPresent(MesWmMiscReceiptDO::getSourceDocCode, reqVO.getSourceDocCode()) + .eqIfPresent(MesWmMiscReceiptDO::getSourceDocType, reqVO.getSourceDocType()) + .eqIfPresent(MesWmMiscReceiptDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesWmMiscReceiptDO::getReceiptDate, reqVO.getReceiptDate()) + .orderByDesc(MesWmMiscReceiptDO::getId)); + } + + default MesWmMiscReceiptDO selectByCode(String code) { + return selectOne(MesWmMiscReceiptDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueDetailMapper.java new file mode 100644 index 000000000..ed28a3cae --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueDetailMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 外协发料单明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmOutsourceIssueDetailMapper extends BaseMapperX { + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmOutsourceIssueDetailDO::getIssueId, issueId); + } + + default List selectListByLineId(Long lineId) { + return selectList(MesWmOutsourceIssueDetailDO::getLineId, lineId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmOutsourceIssueDetailDO::getIssueId, issueId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmOutsourceIssueDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueLineMapper.java new file mode 100644 index 000000000..31e0b2ea5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueLineMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 外协发料单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmOutsourceIssueLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmOutsourceIssueLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmOutsourceIssueLineDO::getIssueId, reqVO.getIssueId()) + .orderByDesc(MesWmOutsourceIssueLineDO::getId)); + } + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmOutsourceIssueLineDO::getIssueId, issueId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmOutsourceIssueLineDO::getIssueId, issueId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java new file mode 100644 index 000000000..48b285515 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 外协发料单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmOutsourceIssueMapper extends BaseMapperX { + + default PageResult selectPage(MesWmOutsourceIssuePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmOutsourceIssueDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmOutsourceIssueDO::getName, reqVO.getName()) + .eqIfPresent(MesWmOutsourceIssueDO::getVendorId, reqVO.getVendorId()) + .eqIfPresent(MesWmOutsourceIssueDO::getWorkOrderId, reqVO.getWorkOrderId()) + .betweenIfPresent(MesWmOutsourceIssueDO::getIssueDate, reqVO.getIssueDate()) + .orderByDesc(MesWmOutsourceIssueDO::getId)); + } + + default MesWmOutsourceIssueDO selectByCode(String code) { + return selectOne(MesWmOutsourceIssueDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptDetailMapper.java new file mode 100644 index 000000000..72a0553b2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptDetailMapper.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt; + +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.wm.outsourcereceipt.MesWmOutsourceReceiptDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 外协入库明细 Mapper + */ +@Mapper +public interface MesWmOutsourceReceiptDetailMapper extends BaseMapperX { + + default List selectListByReceiptId(Long receiptId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmOutsourceReceiptDetailDO::getReceiptId, receiptId) + .orderByAsc(MesWmOutsourceReceiptDetailDO::getId)); + } + + default List selectListByLineId(Long lineId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmOutsourceReceiptDetailDO::getLineId, lineId) + .orderByAsc(MesWmOutsourceReceiptDetailDO::getId)); + } + + default int deleteByReceiptId(Long receiptId) { + return delete(new LambdaQueryWrapperX() + .eq(MesWmOutsourceReceiptDetailDO::getReceiptId, receiptId)); + } + + default int deleteByLineId(Long lineId) { + return delete(new LambdaQueryWrapperX() + .eq(MesWmOutsourceReceiptDetailDO::getLineId, lineId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptLineMapper.java new file mode 100644 index 000000000..5b72682c8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptLineMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line.MesWmOutsourceReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 外协入库单行 Mapper + */ +@Mapper +public interface MesWmOutsourceReceiptLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmOutsourceReceiptLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmOutsourceReceiptLineDO::getReceiptId, reqVO.getReceiptId()) + .eqIfPresent(MesWmOutsourceReceiptLineDO::getItemId, reqVO.getItemId()) + .orderByDesc(MesWmOutsourceReceiptLineDO::getId)); + } + + default List selectListByReceiptId(Long receiptId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmOutsourceReceiptLineDO::getReceiptId, receiptId) + .orderByAsc(MesWmOutsourceReceiptLineDO::getId)); + } + + default int deleteByReceiptId(Long receiptId) { + return delete(new LambdaQueryWrapperX() + .eq(MesWmOutsourceReceiptLineDO::getReceiptId, receiptId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptMapper.java new file mode 100644 index 000000000..695d02185 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourcereceipt/MesWmOutsourceReceiptMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 外协入库单 Mapper + */ +@Mapper +public interface MesWmOutsourceReceiptMapper extends BaseMapperX { + + default PageResult selectPage(MesWmOutsourceReceiptPageReqVO reqVO, java.util.Collection workOrderIds) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmOutsourceReceiptDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmOutsourceReceiptDO::getName, reqVO.getName()) + .eqIfPresent(MesWmOutsourceReceiptDO::getVendorId, reqVO.getVendorId()) + .eqIfPresent(MesWmOutsourceReceiptDO::getStatus, reqVO.getStatus()) + .inIfPresent(MesWmOutsourceReceiptDO::getWorkOrderId, workOrderIds) + .betweenIfPresent(MesWmOutsourceReceiptDO::getReceiptDate, reqVO.getReceiptDate()) + .orderByDesc(MesWmOutsourceReceiptDO::getId)); + } + + default MesWmOutsourceReceiptDO selectByCode(String code) { + return selectOne(MesWmOutsourceReceiptDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageLineMapper.java new file mode 100644 index 000000000..81686cf5f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageLineMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.packages; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPackageLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 装箱明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmPackageLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmPackageLinePageReqVO reqVO, java.util.Collection packageIds) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .inIfPresent(MesWmPackageLineDO::getPackageId, packageIds) + .orderByDesc(MesWmPackageLineDO::getId)); + } + + default void deleteByPackageId(Long packageId) { + delete(MesWmPackageLineDO::getPackageId, packageId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java new file mode 100644 index 000000000..97d6a0d14 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.packages; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmPackageStatusEnum; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * MES 装箱单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmPackageMapper extends BaseMapperX { + + default PageResult selectPage(MesWmPackagePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmPackageDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmPackageDO::getSalesOrderCode, reqVO.getSalesOrderCode()) + .eqIfPresent(MesWmPackageDO::getClientId, reqVO.getClientId()) + .eqIfPresent(MesWmPackageDO::getParentId, reqVO.getParentId()) + .eqIfPresent(MesWmPackageDO::getInspectorUserId, reqVO.getInspectorUserId()) + .orderByDesc(MesWmPackageDO::getId)); + } + + default MesWmPackageDO selectByCode(String code) { + return selectOne(MesWmPackageDO::getCode, code); + } + + default List selectListByParentId(Long parentId) { + return selectList(MesWmPackageDO::getParentId, parentId); + } + + default List selectListByParentIds(Collection parentIds) { + return selectList(new LambdaQueryWrapperX() + .in(MesWmPackageDO::getParentId, parentIds)); + } + + default List selectChildableList() { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmPackageDO::getParentId, MesWmPackageDO.PARENT_ID_ROOT) + .eq(MesWmPackageDO::getStatus, MesWmPackageStatusEnum.FINISHED.getStatus()) + .orderByDesc(MesWmPackageDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueDetailMapper.java new file mode 100644 index 000000000..7987f929c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueDetailMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 领料出库明细 Mapper + */ +@Mapper +public interface MesWmProductIssueDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(MesWmProductIssueDetailDO::getLineId, lineId); + } + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmProductIssueDetailDO::getIssueId, issueId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmProductIssueDetailDO::getIssueId, issueId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmProductIssueDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueLineMapper.java new file mode 100644 index 000000000..265e21ede --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueLineMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 领料出库单行 Mapper + */ +@Mapper +public interface MesWmProductIssueLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmProductIssueLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmProductIssueLineDO::getIssueId, reqVO.getIssueId()) + .orderByDesc(MesWmProductIssueLineDO::getId)); + } + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmProductIssueLineDO::getIssueId, issueId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmProductIssueLineDO::getIssueId, issueId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueMapper.java new file mode 100644 index 000000000..dd18e43a3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productissue/MesWmProductIssueMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssuePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 领料出库单 Mapper + */ +@Mapper +public interface MesWmProductIssueMapper extends BaseMapperX { + + default PageResult selectPage(MesWmProductIssuePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmProductIssueDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmProductIssueDO::getName, reqVO.getName()) + .eqIfPresent(MesWmProductIssueDO::getWorkstationId, reqVO.getWorkstationId()) + .eqIfPresent(MesWmProductIssueDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesWmProductIssueDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesWmProductIssueDO::getIssueDate, reqVO.getIssueDate()) + .orderByDesc(MesWmProductIssueDO::getId)); + } + + default MesWmProductIssueDO selectByCode(String code) { + return selectOne(MesWmProductIssueDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceDetailMapper.java new file mode 100644 index 000000000..cb3348295 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceDetailMapper.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 生产入库明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmProductProduceDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(MesWmProductProduceDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceLineMapper.java new file mode 100644 index 000000000..51a23b593 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceLineMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productproduce.vo.MesWmProductProduceLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 生产入库单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmProductProduceLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmProductProduceLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmProductProduceLineDO::getFeedbackId, reqVO.getFeedbackId()) + .orderByDesc(MesWmProductProduceLineDO::getId)); + } + + default List selectListByProduceId(Long produceId) { + return selectList(MesWmProductProduceLineDO::getProduceId, produceId); + } + + default List selectListByFeedbackId(Long feedbackId) { + return selectList(MesWmProductProduceLineDO::getFeedbackId, feedbackId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceMapper.java new file mode 100644 index 000000000..8928ea490 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productproduce/MesWmProductProduceMapper.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 生产入库单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmProductProduceMapper extends BaseMapperX { + + default MesWmProductProduceDO selectByFeedbackId(Long feedbackId) { + return selectOne(MesWmProductProduceDO::getFeedbackId, feedbackId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptDetailMapper.java new file mode 100644 index 000000000..76f85ab87 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptDetailMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 产品收货单明细 Mapper + */ +@Mapper +public interface MesWmProductReceiptDetailMapper extends BaseMapperX { + + default List selectListByRecptId(Long receiptId) { + return selectList(MesWmProductReceiptDetailDO::getReceiptId, receiptId); + } + + default List selectListByLineId(Long lineId) { + return selectList(MesWmProductReceiptDetailDO::getLineId, lineId); + } + + default void deleteByRecptId(Long receiptId) { + delete(MesWmProductReceiptDetailDO::getReceiptId, receiptId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmProductReceiptDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptLineMapper.java new file mode 100644 index 000000000..11ba3c26a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptLineMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line.MesWmProductReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 产品收货单行 Mapper + */ +@Mapper +public interface MesWmProductReceiptLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmProductReceiptLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmProductReceiptLineDO::getReceiptId, reqVO.getReceiptId()) + .orderByDesc(MesWmProductReceiptLineDO::getId)); + } + + default List selectListByRecptId(Long receiptId) { + return selectList(MesWmProductReceiptLineDO::getReceiptId, receiptId); + } + + default void deleteByRecptId(Long receiptId) { + delete(MesWmProductReceiptLineDO::getReceiptId, receiptId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptMapper.java new file mode 100644 index 000000000..00f5f0254 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productreceipt/MesWmProductReceiptMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 产品收货单 Mapper + */ +@Mapper +public interface MesWmProductReceiptMapper extends BaseMapperX { + + default PageResult selectPage(MesWmProductReceiptPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmProductReceiptDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmProductReceiptDO::getName, reqVO.getName()) + .eqIfPresent(MesWmProductReceiptDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesWmProductReceiptDO::getItemId, reqVO.getItemId()) + .orderByDesc(MesWmProductReceiptDO::getId)); + } + + default MesWmProductReceiptDO selectByCode(String code) { + return selectOne(MesWmProductReceiptDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesDetailMapper.java new file mode 100644 index 000000000..dc72bcf3d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesDetailMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 销售出库明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmProductSalesDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(MesWmProductSalesDetailDO::getLineId, lineId); + } + + default List selectListBySalesId(Long salesId) { + return selectList(MesWmProductSalesDetailDO::getSalesId, salesId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmProductSalesDetailDO::getLineId, lineId); + } + + default void deleteBySalesId(Long salesId) { + delete(MesWmProductSalesDetailDO::getSalesId, salesId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesLineMapper.java new file mode 100644 index 000000000..9dcc9e4c2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesLineMapper.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 销售出库单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmProductSalesLineMapper extends BaseMapperX { + + default List selectListBySalesId(Long salesId) { + return selectList(MesWmProductSalesLineDO::getSalesId, salesId); + } + + default void deleteBySalesId(Long salesId) { + delete(MesWmProductSalesLineDO::getSalesId, salesId); + } + + default cn.iocoder.yudao.framework.common.pojo.PageResult selectPage( + cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLinePageReqVO reqVO) { + return selectPage(reqVO, new cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX() + .eqIfPresent(MesWmProductSalesLineDO::getSalesId, reqVO.getSalesId()) + .inIfPresent(MesWmProductSalesLineDO::getSalesId, reqVO.getSalesIds()) + .orderByDesc(MesWmProductSalesLineDO::getId)); + } + + default void updateQualityStatusByIds(List ids, Integer qualityStatus) { + update(new MesWmProductSalesLineDO().setQualityStatus(qualityStatus), + new LambdaUpdateWrapper().in(MesWmProductSalesLineDO::getId, ids)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java new file mode 100644 index 000000000..e350ee4dc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesMapper.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 销售出库单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmProductSalesMapper extends BaseMapperX { + + default PageResult selectPage(MesWmProductSalesPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmProductSalesDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmProductSalesDO::getName, reqVO.getName()) + .eqIfPresent(MesWmProductSalesDO::getClientId, reqVO.getClientId()) + .eqIfPresent(MesWmProductSalesDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesWmProductSalesDO::getSalesDate, reqVO.getShipmentDate()) + .orderByDesc(MesWmProductSalesDO::getId)); + } + + default MesWmProductSalesDO selectByCode(String code) { + return selectOne(MesWmProductSalesDO::getCode, code); + } + + default List selectListByClientId(Long clientId) { + return selectList(MesWmProductSalesDO::getClientId, clientId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueDetailMapper.java new file mode 100644 index 000000000..a1f185834 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueDetailMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 生产退料明细 Mapper + */ +@Mapper +public interface MesWmReturnIssueDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(MesWmReturnIssueDetailDO::getLineId, lineId); + } + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmReturnIssueDetailDO::getIssueId, issueId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmReturnIssueDetailDO::getIssueId, issueId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmReturnIssueDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueLineMapper.java new file mode 100644 index 000000000..03df6ba99 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueLineMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWmReturnIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 生产退料单行 Mapper + */ +@Mapper +public interface MesWmReturnIssueLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmReturnIssueLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmReturnIssueLineDO::getIssueId, reqVO.getIssueId()) + .orderByDesc(MesWmReturnIssueLineDO::getId)); + } + + default List selectListByIssueId(Long issueId) { + return selectList(MesWmReturnIssueLineDO::getIssueId, issueId); + } + + default void deleteByIssueId(Long issueId) { + delete(MesWmReturnIssueLineDO::getIssueId, issueId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueMapper.java new file mode 100644 index 000000000..f2d561bb4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnissue/MesWmReturnIssueMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.MesWmReturnIssuePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 生产退料单 Mapper + */ +@Mapper +public interface MesWmReturnIssueMapper extends BaseMapperX { + + default PageResult selectPage(MesWmReturnIssuePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmReturnIssueDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmReturnIssueDO::getName, reqVO.getName()) + .eqIfPresent(MesWmReturnIssueDO::getWorkstationId, reqVO.getWorkstationId()) + .eqIfPresent(MesWmReturnIssueDO::getWorkOrderId, reqVO.getWorkOrderId()) + .eqIfPresent(MesWmReturnIssueDO::getType, reqVO.getType()) + .orderByDesc(MesWmReturnIssueDO::getId)); + } + + default MesWmReturnIssueDO selectByCode(String code) { + return selectOne(MesWmReturnIssueDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesDetailMapper.java new file mode 100644 index 000000000..2fc1189b4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesDetailMapper.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail.MesWmReturnSalesDetailPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 销售退货明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmReturnSalesDetailMapper extends BaseMapperX { + + default PageResult selectPage(MesWmReturnSalesDetailPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmReturnSalesDetailDO::getReturnId, reqVO.getReturnId()) + .eqIfPresent(MesWmReturnSalesDetailDO::getLineId, reqVO.getLineId()) + .eqIfPresent(MesWmReturnSalesDetailDO::getItemId, reqVO.getItemId()) + .orderByDesc(MesWmReturnSalesDetailDO::getId)); + } + + default List selectListByReturnId(Long returnId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmReturnSalesDetailDO::getReturnId, returnId)); + } + + default List selectListByLineId(Long lineId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmReturnSalesDetailDO::getLineId, lineId)); + } + + default void deleteByReturnId(Long returnId) { + delete(new LambdaQueryWrapperX() + .eq(MesWmReturnSalesDetailDO::getReturnId, returnId)); + } + + default void deleteByLineId(Long lineId) { + delete(new LambdaQueryWrapperX() + .eq(MesWmReturnSalesDetailDO::getLineId, lineId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesLineMapper.java new file mode 100644 index 000000000..cdefc17d4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesLineMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 销售退货单行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmReturnSalesLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmReturnSalesLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmReturnSalesLineDO::getReturnId, reqVO.getReturnId()) + .eqIfPresent(MesWmReturnSalesLineDO::getItemId, reqVO.getItemId()) + .orderByDesc(MesWmReturnSalesLineDO::getId)); + } + + default List selectListByReturnId(Long returnId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmReturnSalesLineDO::getReturnId, returnId)); + } + + default void deleteByReturnId(Long returnId) { + delete(new LambdaQueryWrapperX() + .eq(MesWmReturnSalesLineDO::getReturnId, returnId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesMapper.java new file mode 100644 index 000000000..8b3942bce --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnsales/MesWmReturnSalesMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 销售退货单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmReturnSalesMapper extends BaseMapperX { + + default PageResult selectPage(MesWmReturnSalesPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmReturnSalesDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmReturnSalesDO::getName, reqVO.getName()) + .likeIfPresent(MesWmReturnSalesDO::getSalesOrderCode, reqVO.getSalesOrderCode()) + .eqIfPresent(MesWmReturnSalesDO::getClientId, reqVO.getClientId()) + .eqIfPresent(MesWmReturnSalesDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesWmReturnSalesDO::getReturnDate, reqVO.getReturnDate()) + .orderByDesc(MesWmReturnSalesDO::getId)); + } + + default MesWmReturnSalesDO selectByCode(String code) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmReturnSalesDO::getCode, code)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorDetailMapper.java new file mode 100644 index 000000000..da49ae008 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorDetailMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 供应商退货明细 Mapper + */ +@Mapper +public interface MesWmReturnVendorDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(MesWmReturnVendorDetailDO::getLineId, lineId); + } + + default List selectListByReturnId(Long returnId) { + return selectList(MesWmReturnVendorDetailDO::getReturnId, returnId); + } + + default void deleteByReturnId(Long returnId) { + delete(MesWmReturnVendorDetailDO::getReturnId, returnId); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmReturnVendorDetailDO::getLineId, lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorLineMapper.java new file mode 100644 index 000000000..ba49cc059 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorLineMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 供应商退货单行 Mapper + */ +@Mapper +public interface MesWmReturnVendorLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmReturnVendorLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmReturnVendorLineDO::getReturnId, reqVO.getReturnId()) + .orderByDesc(MesWmReturnVendorLineDO::getId)); + } + + default List selectListByReturnId(Long returnId) { + return selectList(MesWmReturnVendorLineDO::getReturnId, returnId); + } + + default void deleteByReturnId(Long returnId) { + delete(MesWmReturnVendorLineDO::getReturnId, returnId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorMapper.java new file mode 100644 index 000000000..dfb626fbd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/returnvendor/MesWmReturnVendorMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 供应商退货单 Mapper + */ +@Mapper +public interface MesWmReturnVendorMapper extends BaseMapperX { + + default PageResult selectPage(MesWmReturnVendorPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmReturnVendorDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmReturnVendorDO::getName, reqVO.getName()) + .likeIfPresent(MesWmReturnVendorDO::getPurchaseOrderCode, reqVO.getPurchaseOrderCode()) + .eqIfPresent(MesWmReturnVendorDO::getVendorId, reqVO.getVendorId()) + .orderByDesc(MesWmReturnVendorDO::getId)); + } + + default Long selectCountByVendorId(Long vendorId) { + return selectCount(MesWmReturnVendorDO::getVendorId, vendorId); + } + + default MesWmReturnVendorDO selectByCode(String code) { + return selectOne(MesWmReturnVendorDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeLineMapper.java new file mode 100644 index 000000000..b2eebe689 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeLineMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.salesnotice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line.MesWmSalesNoticeLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 发货通知单行 Mapper + */ +@Mapper +public interface MesWmSalesNoticeLineMapper extends BaseMapperX { + + default PageResult selectPage(MesWmSalesNoticeLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmSalesNoticeLineDO::getNoticeId, reqVO.getNoticeId()) + .orderByDesc(MesWmSalesNoticeLineDO::getId)); + } + + default List selectListByNoticeId(Long noticeId) { + return selectList(MesWmSalesNoticeLineDO::getNoticeId, noticeId); + } + + default void deleteByNoticeId(Long noticeId) { + delete(MesWmSalesNoticeLineDO::getNoticeId, noticeId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java new file mode 100644 index 000000000..de0477749 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.salesnotice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 发货通知单 Mapper + */ +@Mapper +public interface MesWmSalesNoticeMapper extends BaseMapperX { + + default PageResult selectPage(MesWmSalesNoticePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmSalesNoticeDO::getNoticeCode, reqVO.getNoticeCode()) + .likeIfPresent(MesWmSalesNoticeDO::getNoticeName, reqVO.getNoticeName()) + .likeIfPresent(MesWmSalesNoticeDO::getSalesOrderCode, reqVO.getSalesOrderCode()) + .eqIfPresent(MesWmSalesNoticeDO::getClientId, reqVO.getClientId()) + .orderByDesc(MesWmSalesNoticeDO::getId)); + } + + default MesWmSalesNoticeDO selectByNoticeCode(String noticeCode) { + return selectOne(MesWmSalesNoticeDO::getNoticeCode, noticeCode); + } + + default List selectListByStatus(Integer status) { + return selectList(MesWmSalesNoticeDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/sn/MesWmSnMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/sn/MesWmSnMapper.java new file mode 100644 index 000000000..6eb41e81d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/sn/MesWmSnMapper.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.sn; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnGroupRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sn.MesWmSnDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES SN 码 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmSnMapper extends BaseMapperX { + + /** + * 按 UUID 分组查询 SN 码分页(聚合查询) + */ + default PageResult selectPageGroupByUuid(MesWmSnPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + query.eqIfPresent(MesWmSnDO::getUuid, reqVO.getUuid()) + .likeIfPresent(MesWmSnDO::getCode, reqVO.getCode()) + .eqIfPresent(MesWmSnDO::getItemId, reqVO.getItemId()) + .likeIfPresent(MesWmSnDO::getBatchCode, reqVO.getBatchCode()) + .betweenIfPresent(MesWmSnDO::getCreateTime, reqVO.getCreateTime()); + query.selectAs(MesWmSnDO::getUuid, MesWmSnGroupRespVO::getUuid) + .selectMax(MesWmSnDO::getItemId, MesWmSnGroupRespVO::getItemId) + .selectMax(MesWmSnDO::getBatchCode, MesWmSnGroupRespVO::getBatchCode) + .selectMax(MesWmSnDO::getWorkOrderId, MesWmSnGroupRespVO::getWorkOrderId) + .selectMax(MesWmSnDO::getCreateTime, MesWmSnGroupRespVO::getCreateTime) + .selectAs("COUNT(*)", MesWmSnGroupRespVO::getCount) + .groupBy(MesWmSnDO::getUuid) + .last("ORDER BY MAX(t.create_time) DESC"); // 避免 this is incompatible with sql_mode=only_full_group_by 报错 + return selectJoinPage(reqVO, MesWmSnGroupRespVO.class, query); + } + + default List selectListByUuid(String uuid) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmSnDO::getUuid, uuid) + .orderByAsc(MesWmSnDO::getId)); + } + + default int deleteByUuid(String uuid) { + return delete(new LambdaQueryWrapperX() + .eq(MesWmSnDO::getUuid, uuid)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanMapper.java new file mode 100644 index 000000000..b7cd7339a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanMapper.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.MesWmStockTakingPlanPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 盘点方案 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmStockTakingPlanMapper extends BaseMapperX { + + default MesWmStockTakingPlanDO selectByCode(String code) { + return selectOne(MesWmStockTakingPlanDO::getCode, code); + } + + default PageResult selectPage(MesWmStockTakingPlanPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmStockTakingPlanDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmStockTakingPlanDO::getName, reqVO.getName()) + .eqIfPresent(MesWmStockTakingPlanDO::getType, reqVO.getType()) + .orderByDesc(MesWmStockTakingPlanDO::getId)); + } + + default List selectListByStatus(Integer status) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(MesWmStockTakingPlanDO::getStatus, status) + .orderByDesc(MesWmStockTakingPlanDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanParamMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanParamMapper.java new file mode 100644 index 000000000..87342dff5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanParamMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param.MesWmStockTakingPlanParamPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanParamDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 盘点方案参数 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmStockTakingPlanParamMapper extends BaseMapperX { + + default PageResult selectPage(MesWmStockTakingPlanParamPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmStockTakingPlanParamDO::getPlanId, reqVO.getPlanId()) + .orderByAsc(MesWmStockTakingPlanParamDO::getId)); + } + + default List selectListByPlanId(Long planId) { + return selectList(MesWmStockTakingPlanParamDO::getPlanId, planId); + } + + default void deleteByPlanId(Long planId) { + delete(MesWmStockTakingPlanParamDO::getPlanId, planId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskLineMapper.java new file mode 100644 index 000000000..4c2e3a907 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskLineMapper.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line.MesWmStockTakingTaskLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 盘点任务行 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmStockTakingTaskLineMapper extends BaseMapperX { + + default List selectListByTaskId(Long taskId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmStockTakingTaskLineDO::getTaskId, taskId) + .orderByAsc(MesWmStockTakingTaskLineDO::getId)); + } + + default void deleteByTaskId(Long taskId) { + delete(MesWmStockTakingTaskLineDO::getTaskId, taskId); + } + + default PageResult selectPage(MesWmStockTakingTaskLinePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmStockTakingTaskLineDO::getTaskId, reqVO.getTaskId()) + .orderByAsc(MesWmStockTakingTaskLineDO::getId)); + } + + default MesWmStockTakingTaskLineDO selectByTaskIdAndItemIdAndAreaId(Long taskId, Long itemId, Long areaId) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmStockTakingTaskLineDO::getTaskId, taskId) + .eq(MesWmStockTakingTaskLineDO::getItemId, itemId) + .eqIfPresent(MesWmStockTakingTaskLineDO::getAreaId, areaId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskMapper.java new file mode 100644 index 000000000..227d428ec --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.MesWmStockTakingTaskPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 盘点任务 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmStockTakingTaskMapper extends BaseMapperX { + + default MesWmStockTakingTaskDO selectByCode(String code) { + return selectOne(MesWmStockTakingTaskDO::getCode, code); + } + + default PageResult selectPage(MesWmStockTakingTaskPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmStockTakingTaskDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmStockTakingTaskDO::getName, reqVO.getName()) + .eqIfPresent(MesWmStockTakingTaskDO::getType, reqVO.getType()) + .eqIfPresent(MesWmStockTakingTaskDO::getStatus, reqVO.getStatus()) + .eqIfPresent(MesWmStockTakingTaskDO::getUserId, reqVO.getUserId()) + .eqIfPresent(MesWmStockTakingTaskDO::getPlanId, reqVO.getPlanId()) + .betweenIfPresent(MesWmStockTakingTaskDO::getTakingDate, reqVO.getTakingDate()) + .orderByDesc(MesWmStockTakingTaskDO::getId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskResultMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskResultMapper.java new file mode 100644 index 000000000..e9d03c44b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/task/MesWmStockTakingTaskResultMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskResultDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 盘点结果 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesWmStockTakingTaskResultMapper extends BaseMapperX { + + default PageResult selectPage(MesWmStockTakingTaskResultPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesWmStockTakingTaskResultDO::getTaskId, reqVO.getTaskId()) + .eqIfPresent(MesWmStockTakingTaskResultDO::getItemId, reqVO.getItemId()) + .eqIfPresent(MesWmStockTakingTaskResultDO::getWarehouseId, reqVO.getWarehouseId()) + .eqIfPresent(MesWmStockTakingTaskResultDO::getLocationId, reqVO.getLocationId()) + .eqIfPresent(MesWmStockTakingTaskResultDO::getAreaId, reqVO.getAreaId()) + .orderByDesc(MesWmStockTakingTaskResultDO::getId)); + } + + default void deleteByTaskId(Long taskId) { + delete(MesWmStockTakingTaskResultDO::getTaskId, taskId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transaction/MesWmTransactionMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transaction/MesWmTransactionMapper.java new file mode 100644 index 000000000..fee5fe3b5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transaction/MesWmTransactionMapper.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.transaction; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transaction.MesWmTransactionDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 库存事务流水 Mapper + */ +@Mapper +public interface MesWmTransactionMapper extends BaseMapperX { + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferDetailMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferDetailMapper.java new file mode 100644 index 000000000..d6133265c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferDetailMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.transfer; + +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.wm.transfer.MesWmTransferDetailDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 调拨明细 Mapper + */ +@Mapper +public interface MesWmTransferDetailMapper extends BaseMapperX { + + default List selectListByLineId(Long lineId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmTransferDetailDO::getLineId, lineId) + .orderByAsc(MesWmTransferDetailDO::getId)); + } + + default List selectListByTransferId(Long transferId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmTransferDetailDO::getTransferId, transferId) + .orderByAsc(MesWmTransferDetailDO::getId)); + } + + default void deleteByLineId(Long lineId) { + delete(MesWmTransferDetailDO::getLineId, lineId); + } + + default void deleteByTransferId(Long transferId) { + delete(MesWmTransferDetailDO::getTransferId, transferId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferLineMapper.java new file mode 100644 index 000000000..7f73bc9f1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferLineMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.transfer; + +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.wm.transfer.MesWmTransferLineDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 转移单行 Mapper + */ +@Mapper +public interface MesWmTransferLineMapper extends BaseMapperX { + + default List selectListByTransferId(Long transferId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesWmTransferLineDO::getTransferId, transferId) + .orderByAsc(MesWmTransferLineDO::getId)); + } + + default void deleteByTransferId(Long transferId) { + delete(MesWmTransferLineDO::getTransferId, transferId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferMapper.java new file mode 100644 index 000000000..a556a8a3b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/transfer/MesWmTransferMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.transfer; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.MesWmTransferPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 转移单 Mapper + */ +@Mapper +public interface MesWmTransferMapper extends BaseMapperX { + + default PageResult selectPage(MesWmTransferPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmTransferDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmTransferDO::getName, reqVO.getName()) + .eqIfPresent(MesWmTransferDO::getType, reqVO.getType()) + .eqIfPresent(MesWmTransferDO::getStatus, reqVO.getStatus()) + .orderByDesc(MesWmTransferDO::getId)); + } + + default MesWmTransferDO selectByCode(String code) { + return selectOne(MesWmTransferDO::getCode, code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseAreaMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseAreaMapper.java new file mode 100644 index 000000000..68ca7e2b8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseAreaMapper.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area.MesWmWarehouseAreaPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * MES 库位 Mapper + */ +@Mapper +public interface MesWmWarehouseAreaMapper extends BaseMapperX { + + default PageResult selectPage(MesWmWarehouseAreaPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmWarehouseAreaDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmWarehouseAreaDO::getName, reqVO.getName()) + .eqIfPresent(MesWmWarehouseAreaDO::getLocationId, reqVO.getLocationId()) + .eqIfPresent(MesWmWarehouseAreaDO::getPositionX, reqVO.getPositionX()) + .eqIfPresent(MesWmWarehouseAreaDO::getPositionY, reqVO.getPositionY()) + .eqIfPresent(MesWmWarehouseAreaDO::getPositionZ, reqVO.getPositionZ()) + .orderByDesc(MesWmWarehouseAreaDO::getId)); + } + + default MesWmWarehouseAreaDO selectByCode(String code) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmWarehouseAreaDO::getCode, code)); + } + + default MesWmWarehouseAreaDO selectByCode(Long locationId, String code) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmWarehouseAreaDO::getLocationId, locationId) + .eq(MesWmWarehouseAreaDO::getCode, code)); + } + + default MesWmWarehouseAreaDO selectByName(Long locationId, String name) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmWarehouseAreaDO::getLocationId, locationId) + .eq(MesWmWarehouseAreaDO::getName, name)); + } + + default List selectSimpleList(Long locationId) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(MesWmWarehouseAreaDO::getLocationId, locationId) + .orderByDesc(MesWmWarehouseAreaDO::getId)); + } + + default List selectListByIds(Collection ids) { + return selectByIds(ids); + } + + default Long selectCountByLocationId(Long locationId) { + return selectCount(MesWmWarehouseAreaDO::getLocationId, locationId); + } + + /** + * 批量更新指定库区下所有库位 + */ + default void updateByLocationId(Long locationId, MesWmWarehouseAreaDO updateObj) { + update(updateObj, new LambdaQueryWrapperX() + .eq(MesWmWarehouseAreaDO::getLocationId, locationId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseLocationMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseLocationMapper.java new file mode 100644 index 000000000..125bf59f2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseLocationMapper.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * MES 库区 Mapper + */ +@Mapper +public interface MesWmWarehouseLocationMapper extends BaseMapperX { + + default PageResult selectPage(MesWmWarehouseLocationPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmWarehouseLocationDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmWarehouseLocationDO::getName, reqVO.getName()) + .eqIfPresent(MesWmWarehouseLocationDO::getWarehouseId, reqVO.getWarehouseId()) + .orderByDesc(MesWmWarehouseLocationDO::getId)); + } + + default MesWmWarehouseLocationDO selectByCode(Long warehouseId, String code) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmWarehouseLocationDO::getWarehouseId, warehouseId) + .eq(MesWmWarehouseLocationDO::getCode, code)); + } + + default MesWmWarehouseLocationDO selectByCode(String code) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmWarehouseLocationDO::getCode, code)); + } + + default MesWmWarehouseLocationDO selectByName(Long warehouseId, String name) { + return selectOne(new LambdaQueryWrapperX() + .eq(MesWmWarehouseLocationDO::getWarehouseId, warehouseId) + .eq(MesWmWarehouseLocationDO::getName, name)); + } + + default List selectSimpleList(Long warehouseId) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(MesWmWarehouseLocationDO::getWarehouseId, warehouseId) + .orderByDesc(MesWmWarehouseLocationDO::getId)); + } + + default List selectListByIds(Collection ids) { + return selectByIds(ids); + } + + default Long selectCountByWarehouseId(Long warehouseId) { + return selectCount(MesWmWarehouseLocationDO::getWarehouseId, warehouseId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseMapper.java new file mode 100644 index 000000000..2353b9e79 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/warehouse/MesWmWarehouseMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehousePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * MES 仓库 Mapper + */ +@Mapper +public interface MesWmWarehouseMapper extends BaseMapperX { + + default PageResult selectPage(MesWmWarehousePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesWmWarehouseDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmWarehouseDO::getName, reqVO.getName()) + .eqIfPresent(MesWmWarehouseDO::getFrozen, reqVO.getFrozen()) + .orderByDesc(MesWmWarehouseDO::getId)); + } + + default MesWmWarehouseDO selectByCode(String code) { + return selectOne(MesWmWarehouseDO::getCode, code); + } + + default MesWmWarehouseDO selectByName(String name) { + return selectOne(MesWmWarehouseDO::getName, name); + } + + default List selectSimpleList() { + return selectList(new LambdaQueryWrapperX() + .orderByDesc(MesWmWarehouseDO::getId)); + } + + default List selectListByIds(Collection ids) { + return selectByIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java new file mode 100644 index 000000000..26ba06434 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.dal.redis; + +/** + * MES Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface RedisKeyConstants { + + /** + * 编码规则的缓存 + * + * KEY 格式:mes:md:auto_code:{ruleId}:{cycleKey} + * VALUE 数据格式:流水号自增 + */ + String AUTO_CODE = "mes:md:auto_code:"; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/md/autocode/MesMdAutoCodeRedisDAO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/md/autocode/MesMdAutoCodeRedisDAO.java new file mode 100644 index 000000000..9163900e5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/md/autocode/MesMdAutoCodeRedisDAO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.dal.redis.md.autocode; + +import cn.iocoder.yudao.module.mes.dal.redis.RedisKeyConstants; +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import java.time.Duration; + +/** + * MES 编码规则的 Redis DAO + * + * @author 芋道源码 + */ +@Repository +public class MesMdAutoCodeRedisDAO { + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 递增序号(带初始值和循环) + * + * @param keySuffix key 后缀(不包含 prefix) + * @param duration 过期时间 + * @param step 步长 + * @param start 起始值(仅在 key 不存在时使用) + * @return 递增后的值 + */ + public Long increment(String keySuffix, Duration duration, Integer start, Integer step) { + String key = RedisKeyConstants.AUTO_CODE + keySuffix; + + // 情况一:如果 key 不存在,初始化为 startNo + Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(key, String.valueOf(start)); + if (Boolean.TRUE.equals(success)) { + // 设置成功,说明是第一次,设置过期时间并返回 startNo + if (duration != null) { + stringRedisTemplate.expire(key, duration); + } + return start.longValue(); + } + + // 情况二:key 已存在,递增 + Long value = stringRedisTemplate.opsForValue().increment(key, step); + if (duration != null) { + stringRedisTemplate.expire(key, duration); + } + return value; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/package-info.java new file mode 100644 index 000000000..3ef57e7bd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 mes 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.mes.framework; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/rpc/config/RpcConfiguration.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/rpc/config/RpcConfiguration.java new file mode 100644 index 000000000..007778e30 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/rpc/config/RpcConfiguration.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.mes.framework.rpc.config; + +import cn.iocoder.yudao.module.system.api.dept.PostApi; +import cn.iocoder.yudao.module.system.api.permission.RoleApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Configuration; + +@Configuration(value = "mesRpcConfiguration", proxyBeanMethods = false) +@EnableFeignClients(clients = {AdminUserApi.class, PostApi.class, RoleApi.class}) +public class RpcConfiguration { +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/rpc/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/rpc/package-info.java new file mode 100644 index 000000000..8e8b764f1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/rpc/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.mes.framework.rpc; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/security/config/SecurityConfiguration.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/security/config/SecurityConfiguration.java new file mode 100644 index 000000000..290720ee6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/security/config/SecurityConfiguration.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.framework.security.config; + +import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; +import cn.iocoder.yudao.module.mes.enums.ApiConstants; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; + +/** + * Mes 模块的 Security 配置 + */ +@Configuration("mesSecurityConfiguration") +public class SecurityConfiguration { + + @Bean("mesAuthorizeRequestsCustomizer") + public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { + return new AuthorizeRequestsCustomizer() { + + @Override + public void customize(AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry registry) { + // Swagger 接口文档 + registry.requestMatchers("/v3/api-docs/**").permitAll() + .requestMatchers("/webjars/**").permitAll() + .requestMatchers("/swagger-ui").permitAll() + .requestMatchers("/swagger-ui/**").permitAll(); + // Spring Boot Actuator 的安全配置 + registry.requestMatchers("/actuator").permitAll() + .requestMatchers("/actuator/**").permitAll(); + // Druid 监控 + registry.requestMatchers("/druid/**").permitAll(); + // RPC 服务的安全配置 + registry.requestMatchers(ApiConstants.PREFIX + "/**").permitAll(); + } + + }; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/security/core/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/security/core/package-info.java new file mode 100644 index 000000000..269cc31b3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/framework/security/core/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.mes.framework.security.core; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/package-info.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/package-info.java new file mode 100644 index 000000000..e9c462be1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/package-info.java @@ -0,0 +1,10 @@ +/** + * mes 包下,制造执行系统(Manufacturing Execution System)。 + * 例如说:基础数据、排班日历、设备管理、工具管理、生产管理、质量管理、仓库管理等等 + * + * 1. Controller URL:以 /mes/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 mes_ 开头,方便在数据库中区分 + * + * 注意,由于 Mes 模块下,容易和其它模块重名,所以类名都加了 Mes 的前缀~ + */ +package cn.iocoder.yudao.module.mes; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayService.java new file mode 100644 index 000000000..631889390 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayService.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.mes.service.cal.holiday; + +import cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo.MesCalHolidaySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO; +import jakarta.validation.Valid; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * MES 假期设置 Service 接口 + * + * @author 芋道源码 + */ +public interface MesCalHolidayService { + + /** + * 保存假期设置(含 upsert 逻辑:如果该日期已存在记录,则更新) + * + * @param saveReqVO 保存信息 + * @return 编号 + */ + Long saveHoliday(@Valid MesCalHolidaySaveReqVO saveReqVO); + + /** + * 获得假期设置列表 + * + * @param startDay 开始日期(可选) + * @param endDay 结束日期(可选) + * @return 假期设置列表 + */ + List getHolidayList(LocalDateTime startDay, LocalDateTime endDay); + + /** + * 根据日期获得假期设置 + * + * @param day 日期 + * @return 假期设置,不存在则返回 null + */ + MesCalHolidayDO getHolidayByDay(LocalDateTime day); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImpl.java new file mode 100644 index 000000000..050279498 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImpl.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.mes.service.cal.holiday; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo.MesCalHolidaySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.holiday.MesCalHolidayMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * MES 假期设置 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesCalHolidayServiceImpl implements MesCalHolidayService { + + @Resource + private MesCalHolidayMapper holidayMapper; + + @Override + public Long saveHoliday(MesCalHolidaySaveReqVO saveReqVO) { + // Upsert 逻辑:如果该日期已有记录,则更新 + MesCalHolidayDO existing = holidayMapper.selectByDay(saveReqVO.getDay()); + if (existing != null) { + MesCalHolidayDO updateObj = BeanUtils.toBean(saveReqVO, MesCalHolidayDO.class); + updateObj.setId(existing.getId()); + holidayMapper.updateById(updateObj); + return existing.getId(); + } + + // 插入新记录 + MesCalHolidayDO holiday = BeanUtils.toBean(saveReqVO, MesCalHolidayDO.class); + holidayMapper.insert(holiday); + return holiday.getId(); + } + + @Override + public List getHolidayList(LocalDateTime startDay, LocalDateTime endDay) { + return holidayMapper.selectList(startDay, endDay); + } + + @Override + public MesCalHolidayDO getHolidayByDay(LocalDateTime day) { + return holidayMapper.selectByDay(day); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java new file mode 100644 index 000000000..5e141f6b8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.service.cal.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 排班计划 Service 接口 + * + * @author 芋道源码 + */ +public interface MesCalPlanService { + + /** + * 创建排班计划 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPlan(@Valid MesCalPlanSaveReqVO createReqVO); + + /** + * 更新排班计划 + * + * @param updateReqVO 更新信息 + */ + void updatePlan(@Valid MesCalPlanSaveReqVO updateReqVO); + + /** + * 确认排班计划 + * + * @param id 编号 + */ + void confirmPlan(Long id); + + /** + * 删除排班计划 + * + * @param id 编号 + */ + void deletePlan(Long id); + + /** + * 校验排班计划为草稿状态(确认后不允许编辑) + * + * @param planId 计划编号 + * @return 排班计划 + */ + MesCalPlanDO validatePlanPrepare(Long planId); + + /** + * 获得排班计划 + * + * @param id 编号 + * @return 排班计划 + */ + MesCalPlanDO getPlan(Long id); + + /** + * 获得排班计划列表 + * + * @param ids 排班计划编号集合 + * @return 排班计划列表 + */ + List getPlanList(Collection ids); + + /** + * 获得排班计划 Map + * + * @param ids 排班计划编号集合 + * @return 排班计划 Map,key 为编号 + */ + default Map getPlanMap(Collection ids) { + return convertMap(getPlanList(ids), MesCalPlanDO::getId); + } + + /** + * 获得排班计划分页 + * + * @param pageReqVO 分页查询 + * @return 排班计划分页 + */ + PageResult getPlanPage(MesCalPlanPageReqVO pageReqVO); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java new file mode 100644 index 000000000..80f0343be --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java @@ -0,0 +1,171 @@ +package cn.iocoder.yudao.module.mes.service.cal.plan; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalPlanStatusEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService; +import cn.hutool.core.util.ObjUtil; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 排班计划 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesCalPlanServiceImpl implements MesCalPlanService { + + @Resource + private MesCalPlanMapper planMapper; + @Resource + @Lazy + private MesCalPlanShiftService planShiftService; + @Resource + @Lazy + private MesCalPlanTeamService planTeamService; + @Resource + @Lazy + private MesCalTeamShiftService teamShiftService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createPlan(MesCalPlanSaveReqVO createReqVO) { + // 1. 校验编码唯一 + validatePlanCodeUnique(null, createReqVO.getCode()); + + // 2. 插入计划 + MesCalPlanDO plan = BeanUtils.toBean(createReqVO, MesCalPlanDO.class); + plan.setStatus(MesCalPlanStatusEnum.PREPARE.getStatus()); // 默认草稿 + planMapper.insert(plan); + + // 3. 自动生成默认班次 + if (plan.getShiftType() != null) { + planShiftService.addDefaultPlanShift(plan.getId(), plan.getShiftType()); + } + return plan.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePlan(MesCalPlanSaveReqVO updateReqVO) { + // 1.1 校验存在 + MesCalPlanDO existPlan = validatePlanExists(updateReqVO.getId()); + // 1.2 校验计划未确认(已确认不允许编辑) + if (MesCalPlanStatusEnum.CONFIRMED.getStatus().equals(existPlan.getStatus())) { + throw exception(CAL_PLAN_NOT_PREPARE); + } + // 1.3 校验编码唯一 + validatePlanCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 2. 更新 + updateReqVO.setStatus(null); // 不允许通过 update 修改状态,状态变更走专用接口 + MesCalPlanDO updateObj = BeanUtils.toBean(updateReqVO, MesCalPlanDO.class); + planMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void confirmPlan(Long id) { + // 1.1 校验存在 + 校验状态为草稿 + MesCalPlanDO plan = validatePlanPrepare(id); + // 1.2 校验班组数量与轮班方式匹配 + validateTeamCountForConfirm(id, plan.getShiftType()); + + // 2. 更新状态为已确认 + MesCalPlanDO updateObj = new MesCalPlanDO(); + updateObj.setId(id); + updateObj.setStatus(MesCalPlanStatusEnum.CONFIRMED.getStatus()); + planMapper.updateById(updateObj); + + // 3. 生成班组排班记录 + teamShiftService.generateTeamShiftRecords(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePlan(Long id) { + // 1.1 校验存在 + 校验状态为草稿 + validatePlanPrepare(id); + + // 2.1 级联删除班次 + 班组关联 + planShiftService.deletePlanShiftByPlanId(id); + planTeamService.deleteByPlanId(id); + // 2.2 删除计划 + planMapper.deleteById(id); + } + + @Override + public MesCalPlanDO getPlan(Long id) { + return planMapper.selectById(id); + } + + @Override + public List getPlanList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return planMapper.selectByIds(ids); + } + + @Override + public PageResult getPlanPage(MesCalPlanPageReqVO pageReqVO) { + return planMapper.selectPage(pageReqVO); + } + + @Override + public MesCalPlanDO validatePlanPrepare(Long planId) { + MesCalPlanDO plan = validatePlanExists(planId); + if (ObjUtil.notEqual(MesCalPlanStatusEnum.PREPARE.getStatus(), plan.getStatus())) { + throw exception(CAL_PLAN_NOT_PREPARE); + } + return plan; + } + + private MesCalPlanDO validatePlanExists(Long id) { + MesCalPlanDO plan = planMapper.selectById(id); + if (plan == null) { + throw exception(CAL_PLAN_NOT_EXISTS); + } + return plan; + } + + private void validatePlanCodeUnique(Long id, String code) { + MesCalPlanDO plan = planMapper.selectByCode(code); + if (plan == null) { + return; + } + if (id == null || !id.equals(plan.getId())) { + throw exception(CAL_PLAN_CODE_DUPLICATE); + } + } + + /** + * 确认排班计划时,校验班组数量是否与轮班方式匹配 + */ + private void validateTeamCountForConfirm(Long planId, Integer shiftType) { + Long teamCount = planTeamService.getPlanTeamCountByPlanId(planId); + MesCalShiftTypeEnum shiftTypeEnum = MesCalShiftTypeEnum.valueOf(shiftType); + if (teamCount < shiftTypeEnum.getRequiredTeamCount()) { + throw exception(CAL_PLAN_TEAM_COUNT_NOT_MATCH); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftService.java new file mode 100644 index 000000000..1fa08a9d2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftService.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.mes.service.cal.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 计划班次 Service 接口 + * + * @author 芋道源码 + */ +public interface MesCalPlanShiftService { + + /** + * 创建计划班次 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPlanShift(@Valid MesCalPlanShiftSaveReqVO createReqVO); + + /** + * 更新计划班次 + * + * @param updateReqVO 更新信息 + */ + void updatePlanShift(@Valid MesCalPlanShiftSaveReqVO updateReqVO); + + /** + * 删除计划班次 + * + * @param id 编号 + */ + void deletePlanShift(Long id); + + /** + * 获得计划班次 + * + * @param id 编号 + * @return 计划班次 + */ + MesCalPlanShiftDO getPlanShift(Long id); + + /** + * 获得计划班次分页 + * + * @param pageReqVO 分页查询 + * @return 计划班次分页 + */ + PageResult getPlanShiftPage(MesCalPlanShiftPageReqVO pageReqVO); + + /** + * 获得指定排班计划的班次列表 + * + * @param planId 排班计划编号 + * @return 班次列表 + */ + List getPlanShiftListByPlanId(Long planId); + + /** + * 获得指定排班计划的班次数量 + * + * @param planId 排班计划编号 + * @return 班次数量 + */ + Long getPlanShiftCountByPlanId(Long planId); + + /** + * 根据轮班方式添加默认班次 + * + * @param planId 排班计划编号 + * @param shiftType 轮班方式 + */ + void addDefaultPlanShift(Long planId, Integer shiftType); + + /** + * 获得计划班次列表 + * + * @param ids 班次编号集合 + * @return 班次列表 + */ + List getPlanShiftList(Collection ids); + + /** + * 获得计划班次 Map + * + * @param ids 班次编号集合 + * @return 班次 Map,key 为编号 + */ + default Map getPlanShiftMap(Collection ids) { + return convertMap(getPlanShiftList(ids), MesCalPlanShiftDO::getId); + } + + /** + * 根据排班计划编号删除所有班次 + * + * @param planId 排班计划编号 + */ + void deletePlanShiftByPlanId(Long planId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftServiceImpl.java new file mode 100644 index 000000000..6ceb162fc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftServiceImpl.java @@ -0,0 +1,148 @@ +package cn.iocoder.yudao.module.mes.service.cal.plan; + +import cn.hutool.core.lang.Pair; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlanShiftSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanShiftMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import cn.hutool.core.collection.CollUtil; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 计划班次 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesCalPlanShiftServiceImpl implements MesCalPlanShiftService { + + @Resource + private MesCalPlanShiftMapper planShiftMapper; + @Resource + @Lazy + private MesCalPlanService planService; + + @Override + public Long createPlanShift(MesCalPlanShiftSaveReqVO createReqVO) { + // 校验计划未确认 + planService.validatePlanPrepare(createReqVO.getPlanId()); + // 校验班次数量限制 + validatePlanShiftCount(createReqVO.getPlanId()); + + // 插入 + MesCalPlanShiftDO planShift = BeanUtils.toBean(createReqVO, MesCalPlanShiftDO.class); + planShiftMapper.insert(planShift); + return planShift.getId(); + } + + @Override + public void updatePlanShift(MesCalPlanShiftSaveReqVO updateReqVO) { + // 校验存在 + MesCalPlanShiftDO existShift = validatePlanShiftExists(updateReqVO.getId()); + // 校验计划未确认 + planService.validatePlanPrepare(existShift.getPlanId()); + // 更新 + MesCalPlanShiftDO updateObj = BeanUtils.toBean(updateReqVO, MesCalPlanShiftDO.class); + planShiftMapper.updateById(updateObj); + } + + @Override + public void deletePlanShift(Long id) { + // 校验存在 + MesCalPlanShiftDO existShift = validatePlanShiftExists(id); + // 校验计划未确认 + planService.validatePlanPrepare(existShift.getPlanId()); + // 删除 + planShiftMapper.deleteById(id); + } + + private MesCalPlanShiftDO validatePlanShiftExists(Long id) { + MesCalPlanShiftDO shift = planShiftMapper.selectById(id); + if (shift == null) { + throw exception(CAL_PLAN_SHIFT_NOT_EXISTS); + } + return shift; + } + + /** + * 校验班次数量是否超限 + *

+ * 通过 planId 查询已有班次数量,根据排班计划的轮班方式校验 + */ + private void validatePlanShiftCount(Long planId) { + MesCalPlanDO plan = planService.getPlan(planId); + if (plan == null) { + return; + } + Long count = planShiftMapper.selectCountByPlanId(planId); + MesCalShiftTypeEnum shiftTypeEnum = MesCalShiftTypeEnum.valueOf(plan.getShiftType()); + if (count >= shiftTypeEnum.getShiftCount()) { + throw exception(CAL_PLAN_SHIFT_COUNT_EXCEED); + } + } + + @Override + public MesCalPlanShiftDO getPlanShift(Long id) { + return planShiftMapper.selectById(id); + } + + @Override + public PageResult getPlanShiftPage(MesCalPlanShiftPageReqVO pageReqVO) { + return planShiftMapper.selectPage(pageReqVO); + } + + @Override + public List getPlanShiftListByPlanId(Long planId) { + return planShiftMapper.selectListByPlanId(planId); + } + + @Override + public Long getPlanShiftCountByPlanId(Long planId) { + return planShiftMapper.selectCountByPlanId(planId); + } + + @Override + public void addDefaultPlanShift(Long planId, Integer shiftType) { + // 根据轮班方式,通过枚举配置生成默认班次 + MesCalShiftTypeEnum shiftTypeEnum = MesCalShiftTypeEnum.valueOf(shiftType); + List> shifts = shiftTypeEnum.getShifts(); + for (int i = 0; i < shifts.size(); i++) { + Pair shift = shifts.get(i); + MesCalPlanShiftDO planShiftDO = MesCalPlanShiftDO.builder() + .planId(planId).sort(i + 1).name(shift.getKey()) + .startTime(shift.getValue()[0]).endTime(shift.getValue()[1]) + .build(); + planShiftMapper.insert(planShiftDO); + } + } + + @Override + public List getPlanShiftList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return planShiftMapper.selectByIds(ids); + } + + @Override + public void deletePlanShiftByPlanId(Long planId) { + planShiftMapper.deleteByPlanId(planId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanTeamService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanTeamService.java new file mode 100644 index 000000000..4a2392bb6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanTeamService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.service.cal.plan; + +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 计划班组关联 Service 接口 + * + * @author 芋道源码 + */ +public interface MesCalPlanTeamService { + + /** + * 创建计划班组关联 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPlanTeam(@Valid MesCalPlanTeamSaveReqVO createReqVO); + + /** + * 删除计划班组关联 + * + * @param id 编号 + */ + void deletePlanTeam(Long id); + + /** + * 获得指定排班计划的班组列表 + * + * @param planId 排班计划编号 + * @return 班组关联列表 + */ + List getPlanTeamListByPlanId(Long planId); + + /** + * 获得指定排班计划的班组数量 + * + * @param planId 排班计划编号 + * @return 班组数量 + */ + Long getPlanTeamCountByPlanId(Long planId); + + /** + * 根据排班计划编号删除所有班组关联 + * + * @param planId 排班计划编号 + */ + void deleteByPlanId(Long planId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanTeamServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanTeamServiceImpl.java new file mode 100644 index 000000000..48b907286 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanTeamServiceImpl.java @@ -0,0 +1,91 @@ +package cn.iocoder.yudao.module.mes.service.cal.plan; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanTeamMapper; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 计划班组关联 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesCalPlanTeamServiceImpl implements MesCalPlanTeamService { + + @Resource + private MesCalPlanTeamMapper planTeamMapper; + @Resource + @Lazy + private MesCalPlanService planService; + @Resource + @Lazy + private MesCalTeamService teamService; + + @Override + public Long createPlanTeam(MesCalPlanTeamSaveReqVO createReqVO) { + // 校验计划未确认 + planService.validatePlanPrepare(createReqVO.getPlanId()); + // 校验班组存在 + teamService.validateTeamExists(createReqVO.getTeamId()); + // 校验班组不重复 + validatePlanTeamDuplicate(createReqVO.getPlanId(), createReqVO.getTeamId()); + + // 插入 + MesCalPlanTeamDO planTeam = BeanUtils.toBean(createReqVO, MesCalPlanTeamDO.class); + planTeamMapper.insert(planTeam); + return planTeam.getId(); + } + + @Override + public void deletePlanTeam(Long id) { + // 校验存在 + MesCalPlanTeamDO existPlanTeam = validatePlanTeamExists(id); + // 校验计划未确认 + planService.validatePlanPrepare(existPlanTeam.getPlanId()); + // 删除 + planTeamMapper.deleteById(id); + } + + private MesCalPlanTeamDO validatePlanTeamExists(Long id) { + MesCalPlanTeamDO planTeam = planTeamMapper.selectById(id); + if (planTeam == null) { + throw exception(CAL_PLAN_TEAM_NOT_EXISTS); + } + return planTeam; + } + + private void validatePlanTeamDuplicate(Long planId, Long teamId) { + MesCalPlanTeamDO planTeam = planTeamMapper.selectByPlanIdAndTeamId(planId, teamId); + if (planTeam != null) { + throw exception(CAL_PLAN_TEAM_DUPLICATE); + } + } + + @Override + public List getPlanTeamListByPlanId(Long planId) { + return planTeamMapper.selectListByPlanId(planId); + } + + @Override + public Long getPlanTeamCountByPlanId(Long planId) { + return planTeamMapper.selectCountByPlanId(planId); + } + + @Override + public void deleteByPlanId(Long planId) { + planTeamMapper.deleteByPlanId(planId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamMemberService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamMemberService.java new file mode 100644 index 000000000..8713b2c33 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamMemberService.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.mes.service.cal.team; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * MES 班组成员 Service 接口 + * + * @author 芋道源码 + */ +public interface MesCalTeamMemberService { + + /** + * 创建班组成员 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTeamMember(@Valid MesCalTeamMemberSaveReqVO createReqVO); + + /** + * 删除班组成员 + * + * @param id 编号 + */ + void deleteTeamMember(Long id); + + /** + * 获得班组成员 + * + * @param id 编号 + * @return 班组成员 + */ + MesCalTeamMemberDO getTeamMember(Long id); + + /** + * 获得班组成员分页 + * + * @param pageReqVO 分页查询 + * @return 班组成员分页 + */ + PageResult getTeamMemberPage(MesCalTeamMemberPageReqVO pageReqVO); + + /** + * 获得指定班组的成员列表 + * + * @param teamId 班组编号 + * @return 班组成员列表 + */ + List getTeamMemberListByTeamId(Long teamId); + + /** + * 获得指定多个班组的成员列表 + * + * @param teamIds 班组编号列表 + * @return 班组成员列表 + */ + List getTeamMemberListByTeamIds(Collection teamIds); + + /** + * 根据用户编号获得班组成员 + * + * @param userId 用户编号 + * @return 班组成员,不存在则返回 null + */ + MesCalTeamMemberDO getTeamMemberByUserId(Long userId); + + /** + * 根据班组编号删除所有成员 + * + * @param teamId 班组编号 + */ + void deleteByTeamId(Long teamId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamMemberServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamMemberServiceImpl.java new file mode 100644 index 000000000..dcf717ae8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamMemberServiceImpl.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.mes.service.cal.team; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.member.MesCalTeamMemberSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamMemberMapper; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 班组成员 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesCalTeamMemberServiceImpl implements MesCalTeamMemberService { + + @Resource + private MesCalTeamMemberMapper teamMemberMapper; + @Resource + @Lazy + private MesCalTeamService teamService; + @Resource + private AdminUserApi adminUserApi; + + @Override + public Long createTeamMember(MesCalTeamMemberSaveReqVO createReqVO) { + // 1.1 校验班组存在 + teamService.validateTeamExists(createReqVO.getTeamId()); + // 1.2 校验用户存在 + validateUserExists(createReqVO.getUserId()); + // 1.3 校验用户未分配到其他班组 + validateUserUnique(createReqVO.getUserId()); + + // 2. 插入 + MesCalTeamMemberDO member = BeanUtils.toBean(createReqVO, MesCalTeamMemberDO.class); + teamMemberMapper.insert(member); + return member.getId(); + } + + @Override + public void deleteTeamMember(Long id) { + // 校验存在 + validateTeamMemberExists(id); + // 删除 + teamMemberMapper.deleteById(id); + } + + @Override + public MesCalTeamMemberDO getTeamMember(Long id) { + return teamMemberMapper.selectById(id); + } + + @Override + public PageResult getTeamMemberPage(MesCalTeamMemberPageReqVO pageReqVO) { + return teamMemberMapper.selectPage(pageReqVO); + } + + @Override + public List getTeamMemberListByTeamId(Long teamId) { + return teamMemberMapper.selectListByTeamId(teamId); + } + + @Override + public List getTeamMemberListByTeamIds(Collection teamIds) { + return teamMemberMapper.selectListByTeamIds(teamIds); + } + + @Override + public MesCalTeamMemberDO getTeamMemberByUserId(Long userId) { + return teamMemberMapper.selectByUserId(userId); + } + + @Override + public void deleteByTeamId(Long teamId) { + teamMemberMapper.deleteByTeamId(teamId); + } + + private void validateTeamMemberExists(Long id) { + if (teamMemberMapper.selectById(id) == null) { + throw exception(CAL_TEAM_MEMBER_NOT_EXISTS); + } + } + + private void validateUserExists(Long userId) { + if (adminUserApi.getUser(userId) == null) { + throw exception(CAL_TEAM_MEMBER_USER_NOT_EXISTS); + } + } + + private void validateUserUnique(Long userId) { + if (teamMemberMapper.selectByUserId(userId) != null) { + throw exception(CAL_TEAM_MEMBER_USER_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamService.java new file mode 100644 index 000000000..5251559d3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamService.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.service.cal.team; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 班组 Service 接口 + * + * @author 芋道源码 + */ +public interface MesCalTeamService { + + /** + * 创建班组 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTeam(@Valid MesCalTeamSaveReqVO createReqVO); + + /** + * 更新班组 + * + * @param updateReqVO 更新信息 + */ + void updateTeam(@Valid MesCalTeamSaveReqVO updateReqVO); + + /** + * 删除班组 + * + * @param id 编号 + */ + void deleteTeam(Long id); + + /** + * 获得班组 + * + * @param id 编号 + * @return 班组 + */ + MesCalTeamDO getTeam(Long id); + + /** + * 获得班组分页 + * + * @param pageReqVO 分页查询 + * @return 班组分页 + */ + PageResult getTeamPage(MesCalTeamPageReqVO pageReqVO); + + /** + * 获得班组列表(全量,用于下拉选择) + * + * @return 班组列表 + */ + List getTeamList(); + + /** + * 获得班组列表 + * + * @param ids 班组编号集合 + * @return 班组列表 + */ + List getTeamList(Collection ids); + + /** + * 获得班组 Map + * + * @param ids 班组编号集合 + * @return 班组 Map,key 为编号 + */ + default Map getTeamMap(Collection ids) { + return convertMap(getTeamList(ids), MesCalTeamDO::getId); + } + + /** + * 校验班组存在 + * + * @param id 编号 + * @return 班组 + */ + MesCalTeamDO validateTeamExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamServiceImpl.java new file mode 100644 index 000000000..70cc6f9d3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamServiceImpl.java @@ -0,0 +1,121 @@ +package cn.iocoder.yudao.module.mes.service.cal.team; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 班组 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesCalTeamServiceImpl implements MesCalTeamService { + + @Resource + private MesCalTeamMapper teamMapper; + @Resource + @Lazy + private MesCalTeamMemberService teamMemberService; + @Resource + @Lazy + private MesCalTeamShiftService teamShiftService; + + @Override + public Long createTeam(MesCalTeamSaveReqVO createReqVO) { + // 1. 校验编码唯一 + validateTeamCodeUnique(null, createReqVO.getCode()); + + // 2. 插入 + MesCalTeamDO team = BeanUtils.toBean(createReqVO, MesCalTeamDO.class); + teamMapper.insert(team); + return team.getId(); + } + + @Override + public void updateTeam(MesCalTeamSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateTeamExists(updateReqVO.getId()); + // 1.2 校验编码唯一 + validateTeamCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 2. 更新 + MesCalTeamDO updateObj = BeanUtils.toBean(updateReqVO, MesCalTeamDO.class); + teamMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteTeam(Long id) { + // 1. 校验存在 + validateTeamExists(id); + + // 2.1 级联删除成员 + teamMemberService.deleteByTeamId(id); + // 2.2 级联删除排班记录 + teamShiftService.deleteByTeamId(id); + // 2.3 删除班组 + teamMapper.deleteById(id); + } + + @Override + public MesCalTeamDO getTeam(Long id) { + return teamMapper.selectById(id); + } + + @Override + public PageResult getTeamPage(MesCalTeamPageReqVO pageReqVO) { + return teamMapper.selectPage(pageReqVO); + } + + @Override + public List getTeamList() { + return teamMapper.selectList(); + } + + @Override + public List getTeamList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return teamMapper.selectByIds(ids); + } + + @Override + public MesCalTeamDO validateTeamExists(Long id) { + MesCalTeamDO team = teamMapper.selectById(id); + if (team == null) { + throw exception(CAL_TEAM_NOT_EXISTS); + } + return team; + } + + private void validateTeamCodeUnique(Long id, String code) { + MesCalTeamDO team = teamMapper.selectByCode(code); + if (team == null) { + return; + } + if (ObjUtil.notEqual(id, team.getId())) { + throw exception(CAL_TEAM_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftService.java new file mode 100644 index 000000000..47536ecdf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftService.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.service.cal.team; + +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO; + +import java.util.List; + +/** + * MES 班组排班 Service 接口 + * + * @author 芋道源码 + */ +public interface MesCalTeamShiftService { + + /** + * 根据排班计划生成班组排班记录 + * + * @param planId 排班计划编号 + */ + void generateTeamShiftRecords(Long planId); + + /** + * 获得班组排班列表 + * + * @param reqVO 查询条件 + * @return 班组排班列表 + */ + List getTeamShiftList(MesCalTeamShiftListReqVO reqVO); + + /** + * 根据排班计划编号删除所有排班记录 + * + * @param planId 排班计划编号 + */ + void deleteByPlanId(Long planId); + + /** + * 根据班组编号删除所有排班记录 + * + * @param teamId 班组编号 + */ + void deleteByTeamId(Long teamId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java new file mode 100644 index 000000000..885ebd9f8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java @@ -0,0 +1,245 @@ +package cn.iocoder.yudao.module.mes.service.cal.team; + +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamShiftMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanTeamService; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_TEAM_NOT_ENOUGH; + +/** + * MES 班组排班 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService { + + @Resource + private MesCalTeamShiftMapper teamShiftMapper; + @Resource + @Lazy + private MesCalPlanService planService; + @Resource + @Lazy + private MesCalPlanShiftService planShiftService; + @Resource + @Lazy + private MesCalPlanTeamService planTeamService; + + @Transactional(rollbackFor = Exception.class) + @Override + public void generateTeamShiftRecords(Long planId) { + // 1.1 查询排班计划 + MesCalPlanDO plan = planService.getPlan(planId); + // 1.2 查询计划中的班次列表 + List shifts = planShiftService.getPlanShiftListByPlanId(planId); + // 1.3 查询计划中的班组列表 + List teams = planTeamService.getPlanTeamListByPlanId(planId); + // 1.4 校验班组和班次数量是否满足班型要求 + MesCalShiftTypeEnum shiftTypeEnum = MesCalShiftTypeEnum.valueOf(plan.getShiftType()); + int requiredCount = shiftTypeEnum.getRequiredTeamCount(); + if (teams.size() < requiredCount) { + throw exception(CAL_TEAM_SHIFT_GENERATE_TEAM_NOT_ENOUGH); + } + if (shifts.size() < requiredCount) { + throw exception(CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH); + } + + // 2. 计算日期跨度,遍历每天生成排班记录,最后统一写入数据库 + LocalDate startDate = plan.getStartDate().toLocalDate(); + LocalDate endDate = plan.getEndDate().toLocalDate(); + long days = ChronoUnit.DAYS.between(startDate, endDate) + 1; + List allRecords = new ArrayList<>(); + int shiftIndex = 0; + for (int i = 0; i < days; i++) { + LocalDate currentDate = startDate.plusDays(i); + LocalDateTime currentDay = currentDate.atStartOfDay(); + // 2.2.1 根据倒班方式计算 shiftIndex + shiftIndex = calculateShiftIndex(shiftIndex, i, currentDate, startDate, plan); + // 2.2.2 根据轮班方式生成排班记录,收集到列表 + buildRecordsForDay(allRecords, planId, currentDay, shiftIndex, plan.getShiftType(), teams, shifts); + } + + // 3. 批量插入排班记录 + teamShiftMapper.insertBatch(allRecords); + } + + /** + * 计算当天的 shiftIndex(根据倒班方式判断是否需要递增) + */ + private int calculateShiftIndex(int shiftIndex, int dayOffset, LocalDate currentDate, + LocalDate startDate, MesCalPlanDO plan) { + if (dayOffset == 0) { + return shiftIndex; // 第一天不递增 + } + if (MesCalShiftMethodEnum.QUARTER.getMethod().equals(plan.getShiftMethod())) { + // 按季度轮班:到了新季度的第一天 + LocalDate quarterStart = LocalDateTimeUtils.getQuarterStart(currentDate); + LocalDate planQuarterStart = LocalDateTimeUtils.getQuarterStart(startDate); + if (currentDate.equals(quarterStart) && !quarterStart.equals(planQuarterStart)) { + return shiftIndex + 1; + } + } else if (MesCalShiftMethodEnum.MONTH.getMethod().equals(plan.getShiftMethod())) { + // 按月轮班:到了月初 + LocalDate monthStart = currentDate.withDayOfMonth(1); + LocalDate planMonthStart = startDate.withDayOfMonth(1); + if (currentDate.equals(monthStart) && !monthStart.equals(planMonthStart)) { + return shiftIndex + 1; + } + } else if (MesCalShiftMethodEnum.WEEK.getMethod().equals(plan.getShiftMethod())) { + // 按周轮班:到了周一 + LocalDate weekStart = LocalDateTimeUtils.getWeekStart(currentDate); + LocalDate planWeekStart = LocalDateTimeUtils.getWeekStart(startDate); + if (currentDate.equals(weekStart) && !weekStart.equals(planWeekStart)) { + return shiftIndex + 1; + } + } else if (MesCalShiftMethodEnum.DAY.getMethod().equals(plan.getShiftMethod())) { + // 按天轮班:到了指定轮班天数的倍数 + if (dayOffset % plan.getShiftCount() == 0) { + return shiftIndex + 1; + } + } else { + throw new IllegalArgumentException("不支持的倒班方式: " + plan.getShiftMethod()); + } + return shiftIndex; + } + + /** + * 根据班型生成当天的排班记录,添加到 allRecords 列表 + */ + private void buildRecordsForDay(List allRecords, Long planId, + LocalDateTime currentDay, int shiftIndex, Integer shiftType, + List teams, List shifts) { + if (MesCalShiftTypeEnum.SINGLE.getType().equals(shiftType)) { + // 单白班:不需要倒班 + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId) + .day(currentDay) + .teamId(teams.get(0).getTeamId()) + .shiftId(shifts.get(0).getId()) + .sort(1).build()); + } else if (MesCalShiftTypeEnum.TWO.getType().equals(shiftType)) { + // 两班倒 + if (shiftIndex % 2 == 0) { + // A 组上白班 + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(0).getTeamId()) + .shiftId(shifts.get(0).getId()) + .sort(1).build()); + // B 组上夜班 + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(1).getTeamId()) + .shiftId(shifts.get(1).getId()) + .sort(2).build()); + } else { + // A 组上夜班 + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(0).getTeamId()) + .shiftId(shifts.get(1).getId()) + .sort(2).build()); + // B 组上白班 + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(1).getTeamId()) + .shiftId(shifts.get(0).getId()) + .sort(1).build()); + } + } else if (MesCalShiftTypeEnum.THREE.getType().equals(shiftType)) { + // 三班倒 + if (shiftIndex % 3 == 0) { + // A 组上白班、B 组上中班、C 组上夜班 + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(0).getTeamId()) + .shiftId(shifts.get(0).getId()) + .sort(1).build()); + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(1).getTeamId()) + .shiftId(shifts.get(1).getId()) + .sort(2).build()); + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(2).getTeamId()) + .shiftId(shifts.get(2).getId()) + .sort(3).build()); + } else if (shiftIndex % 3 == 1) { + // A 组上中班、B 组上夜班、C 组上白班 + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(0).getTeamId()) + .shiftId(shifts.get(1).getId()) + .sort(2).build()); + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(1).getTeamId()) + .shiftId(shifts.get(2).getId()) + .sort(3).build()); + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(2).getTeamId()) + .shiftId(shifts.get(0).getId()) + .sort(1).build()); + } else { + // A 组上夜班、B 组上白班、C 组上中班 + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(0).getTeamId()) + .shiftId(shifts.get(2).getId()) + .sort(3).build()); + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(1).getTeamId()) + .shiftId(shifts.get(0).getId()) + .sort(1).build()); + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(2).getTeamId()) + .shiftId(shifts.get(1).getId()) + .sort(2).build()); + } + } + } + + @Override + public List getTeamShiftList(MesCalTeamShiftListReqVO reqVO) { + return teamShiftMapper.selectList(reqVO); + } + + @Override + public void deleteByPlanId(Long planId) { + teamShiftMapper.deleteByPlanId(planId); + } + + @Override + public void deleteByTeamId(Long teamId) { + teamShiftMapper.deleteByTeamId(teamId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanMachineryService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanMachineryService.java new file mode 100644 index 000000000..e82ca8e8e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanMachineryService.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkplan; + +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery.MesDvCheckPlanMachinerySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanMachineryDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 点检保养方案设备 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvCheckPlanMachineryService { + + /** + * 创建方案设备关联 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCheckPlanMachinery(@Valid MesDvCheckPlanMachinerySaveReqVO createReqVO); + + /** + * 删除方案设备关联 + * + * @param id 编号 + */ + void deleteCheckPlanMachinery(Long id); + + /** + * 获得指定方案的设备列表 + * + * @param planId 方案编号 + * @return 设备关联列表 + */ + List getCheckPlanMachineryListByPlanId(Long planId); + + /** + * 获得指定方案的设备数量 + * + * @param planId 方案编号 + * @return 设备数量 + */ + Long getCheckPlanMachineryCountByPlanId(Long planId); + + /** + * 根据方案编号删除所有设备关联 + * + * @param planId 方案编号 + */ + void deleteByPlanId(Long planId); + + /** + * 获得指定设备关联的方案设备数量 + * + * @param machineryId 设备编号 + * @return 方案设备数量 + */ + Long getCheckPlanMachineryCountByMachineryId(Long machineryId); + + /** + * 获得指定设备关联的方案设备列表 + * + * @param machineryId 设备编号 + * @return 方案设备列表 + */ + List getCheckPlanMachineryListByMachineryId(Long machineryId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanMachineryServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanMachineryServiceImpl.java new file mode 100644 index 000000000..73839b709 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanMachineryServiceImpl.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkplan; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.machinery.MesDvCheckPlanMachinerySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanMachineryDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.checkplan.MesDvCheckPlanMachineryMapper; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 点检保养方案设备 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvCheckPlanMachineryServiceImpl implements MesDvCheckPlanMachineryService { + + @Resource + private MesDvCheckPlanMachineryMapper checkPlanMachineryMapper; + + @Resource + @Lazy + private MesDvCheckPlanService checkPlanService; + @Resource + private MesDvMachineryService machineryService; + + @Override + public Long createCheckPlanMachinery(MesDvCheckPlanMachinerySaveReqVO createReqVO) { + // 1.1 校验方案草稿状态 + MesDvCheckPlanDO currentPlan = checkPlanService.validateCheckPlanPrepare(createReqVO.getPlanId()); + // 1.2 校验设备存在 + machineryService.validateMachineryExists(createReqVO.getMachineryId()); + // 1.3 校验同一方案下设备不重复 + if (checkPlanMachineryMapper.selectByPlanIdAndMachineryId(createReqVO.getPlanId(), createReqVO.getMachineryId()) != null) { + throw exception(DV_CHECK_PLAN_MACHINERY_DUPLICATE); + } + // 1.4 跨方案类型唯一性校验(设备不能存在于同类型多个方案中) + List existingMachineryList = getCheckPlanMachineryListByMachineryId(createReqVO.getMachineryId()); + if (CollUtil.isNotEmpty(existingMachineryList)) { + List existingPlanIds = existingMachineryList.stream().map(MesDvCheckPlanMachineryDO::getPlanId).toList(); + List existingPlans = checkPlanService.getCheckPlanList(existingPlanIds); + for (MesDvCheckPlanDO existPlan : existingPlans) { + // 如果存在不同于当前方案、但类型一致的计划方案,则拦截(一机多计划,但不允许同一机多同类型计划) + if (ObjUtil.notEqual(existPlan.getId(), currentPlan.getId()) + && ObjUtil.equal(existPlan.getType(), currentPlan.getType())) { + throw exception(DV_CHECK_PLAN_MACHINERY_EXISTS_IN_SAME_TYPE); + } + } + } + + // 2. 插入 + MesDvCheckPlanMachineryDO planMachinery = BeanUtils.toBean(createReqVO, MesDvCheckPlanMachineryDO.class); + checkPlanMachineryMapper.insert(planMachinery); + return planMachinery.getId(); + } + + @Override + public void deleteCheckPlanMachinery(Long id) { + // 1.1 校验存在 + MesDvCheckPlanMachineryDO existRecord = checkPlanMachineryMapper.selectById(id); + if (existRecord == null) { + throw exception(DV_CHECK_PLAN_MACHINERY_NOT_EXISTS); + } + // 1.2 校验方案草稿状态 + checkPlanService.validateCheckPlanPrepare(existRecord.getPlanId()); + + // 2. 删除 + checkPlanMachineryMapper.deleteById(id); + } + + @Override + public List getCheckPlanMachineryListByPlanId(Long planId) { + return checkPlanMachineryMapper.selectListByPlanId(planId); + } + + @Override + public Long getCheckPlanMachineryCountByPlanId(Long planId) { + return checkPlanMachineryMapper.selectCountByPlanId(planId); + } + + @Override + public void deleteByPlanId(Long planId) { + checkPlanMachineryMapper.deleteByPlanId(planId); + } + + @Override + public Long getCheckPlanMachineryCountByMachineryId(Long machineryId) { + return checkPlanMachineryMapper.selectCountByMachineryId(machineryId); + } + + @Override + public List getCheckPlanMachineryListByMachineryId(Long machineryId) { + return checkPlanMachineryMapper.selectListByMachineryId(machineryId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java new file mode 100644 index 000000000..bfb1fe2f7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkplan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 点检保养方案 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvCheckPlanService { + + /** + * 创建点检保养方案 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCheckPlan(@Valid MesDvCheckPlanSaveReqVO createReqVO); + + /** + * 更新点检保养方案 + * + * @param updateReqVO 更新信息 + */ + void updateCheckPlan(@Valid MesDvCheckPlanSaveReqVO updateReqVO); + + /** + * 启用点检保养方案 + * + * @param id 编号 + */ + void enableCheckPlan(Long id); + + /** + * 停用点检保养方案 + * + * @param id 编号 + */ + void disableCheckPlan(Long id); + + /** + * 删除点检保养方案 + * + * @param id 编号 + */ + void deleteCheckPlan(Long id); + + /** + * 校验点检保养方案存在 + * + * @param id 编号 + */ + void validateCheckPlanExists(Long id); + + /** + * 校验点检保养方案为草稿状态 + * + * @param planId 方案编号 + * @return 方案 + */ + MesDvCheckPlanDO validateCheckPlanPrepare(Long planId); + + /** + * 获得点检保养方案 + * + * @param id 编号 + * @return 方案 + */ + MesDvCheckPlanDO getCheckPlan(Long id); + + /** + * 获得点检保养方案分页 + * + * @param pageReqVO 分页查询 + * @return 方案分页 + */ + PageResult getCheckPlanPage(MesDvCheckPlanPageReqVO pageReqVO); + + /** + * 获得点检保养方案列表 + * + * @param ids 编号数组 + * @return 方案列表 + */ + List getCheckPlanList(Collection ids); + + /** + * 获得点检保养方案 Map + * + * @param ids 编号数组 + * @return 方案 Map + */ + default Map getCheckPlanMap(Collection ids) { + return convertMap(getCheckPlanList(ids), MesDvCheckPlanDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java new file mode 100644 index 000000000..644a149f2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java @@ -0,0 +1,170 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkplan; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.MesDvCheckPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.checkplan.MesDvCheckPlanMapper; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckPlanStatusEnum; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 点检保养方案 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvCheckPlanServiceImpl implements MesDvCheckPlanService { + + @Resource + private MesDvCheckPlanMapper checkPlanMapper; + @Resource + @Lazy + private MesDvCheckPlanMachineryService checkPlanMachineryService; + @Resource + @Lazy + private MesDvCheckPlanSubjectService checkPlanSubjectService; + + @Override + public Long createCheckPlan(MesDvCheckPlanSaveReqVO createReqVO) { + // 1. 校验编码唯一 + validateCheckPlanCodeUnique(null, createReqVO.getCode()); + + // 2. 插入方案 + MesDvCheckPlanDO checkPlan = BeanUtils.toBean(createReqVO, MesDvCheckPlanDO.class); + checkPlan.setStatus(MesDvCheckPlanStatusEnum.PREPARE.getStatus()); // 默认草稿 + checkPlanMapper.insert(checkPlan); + return checkPlan.getId(); + } + + @Override + public void updateCheckPlan(MesDvCheckPlanSaveReqVO updateReqVO) { + // 1.1 校验存在 + MesDvCheckPlanDO existPlan = doValidateCheckPlanExists(updateReqVO.getId()); + // 1.2 校验草稿状态 + if (ObjUtil.notEqual(MesDvCheckPlanStatusEnum.PREPARE.getStatus(), existPlan.getStatus())) { + throw exception(DV_CHECK_PLAN_NOT_PREPARE); + } + // 1.3 校验编码唯一 + validateCheckPlanCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 2. 更新 + updateReqVO.setStatus(null); // 不允许通过 update 修改状态 + MesDvCheckPlanDO updateObj = BeanUtils.toBean(updateReqVO, MesDvCheckPlanDO.class); + checkPlanMapper.updateById(updateObj); + } + + @Override + public void enableCheckPlan(Long id) { + // 1.1 校验存在 + 校验草稿状态 + validateCheckPlanPrepare(id); + // 1.2 校验至少关联一台设备 + Long machineryCount = checkPlanMachineryService.getCheckPlanMachineryCountByPlanId(id); + if (machineryCount <= 0) { + throw exception(DV_CHECK_PLAN_NO_MACHINERY); + } + // 1.3 校验至少关联一个项目 + Long subjectCount = checkPlanSubjectService.getCheckPlanSubjectCountByPlanId(id); + if (subjectCount <= 0) { + throw exception(DV_CHECK_PLAN_NO_SUBJECT); + } + + // 2. 更新状态为已启用 + checkPlanMapper.updateById(new MesDvCheckPlanDO().setId(id) + .setStatus(MesDvCheckPlanStatusEnum.ENABLED.getStatus())); + } + + @Override + public void disableCheckPlan(Long id) { + // 1. 校验存在 + 校验已启用状态 + MesDvCheckPlanDO plan = doValidateCheckPlanExists(id); + if (ObjUtil.notEqual(MesDvCheckPlanStatusEnum.ENABLED.getStatus(), plan.getStatus())) { + throw exception(DV_CHECK_PLAN_NOT_ENABLED); + } + + // 2. 更新状态为草稿 + checkPlanMapper.updateById(new MesDvCheckPlanDO().setId(id) + .setStatus(MesDvCheckPlanStatusEnum.PREPARE.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteCheckPlan(Long id) { + // 1. 校验存在 + 校验草稿状态 + validateCheckPlanPrepare(id); + + // 2.1 级联删除设备关联 + 项目关联 + checkPlanMachineryService.deleteByPlanId(id); + checkPlanSubjectService.deleteByPlanId(id); + // 2.2 删除方案 + checkPlanMapper.deleteById(id); + } + + @Override + public MesDvCheckPlanDO validateCheckPlanPrepare(Long planId) { + MesDvCheckPlanDO plan = doValidateCheckPlanExists(planId); + if (ObjUtil.notEqual(MesDvCheckPlanStatusEnum.PREPARE.getStatus(), plan.getStatus())) { + throw exception(DV_CHECK_PLAN_NOT_PREPARE); + } + return plan; + } + + @Override + public MesDvCheckPlanDO getCheckPlan(Long id) { + return checkPlanMapper.selectById(id); + } + + @Override + public PageResult getCheckPlanPage(MesDvCheckPlanPageReqVO pageReqVO) { + return checkPlanMapper.selectPage(pageReqVO); + } + + @Override + public void validateCheckPlanExists(Long id) { + if (checkPlanMapper.selectById(id) == null) { + throw exception(DV_CHECK_PLAN_NOT_EXISTS); + } + } + + private MesDvCheckPlanDO doValidateCheckPlanExists(Long id) { + MesDvCheckPlanDO plan = checkPlanMapper.selectById(id); + if (plan == null) { + throw exception(DV_CHECK_PLAN_NOT_EXISTS); + } + return plan; + } + + private void validateCheckPlanCodeUnique(Long id, String code) { + MesDvCheckPlanDO plan = checkPlanMapper.selectByCode(code); + if (plan == null) { + return; + } + if (ObjUtil.notEqual(plan.getId(), id)) { + throw exception(DV_CHECK_PLAN_CODE_DUPLICATE); + } + } + + @Override + public List getCheckPlanList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return checkPlanMapper.selectByIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectService.java new file mode 100644 index 000000000..710d55b9c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectService.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkplan; + +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject.MesDvCheckPlanSubjectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanSubjectDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 点检保养方案项目 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvCheckPlanSubjectService { + + /** + * 创建方案项目关联 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCheckPlanSubject(@Valid MesDvCheckPlanSubjectSaveReqVO createReqVO); + + /** + * 删除方案项目关联 + * + * @param id 编号 + */ + void deleteCheckPlanSubject(Long id); + + /** + * 获得指定方案的项目列表 + * + * @param planId 方案编号 + * @return 项目关联列表 + */ + List getCheckPlanSubjectListByPlanId(Long planId); + + /** + * 获得指定方案的项目数量 + * + * @param planId 方案编号 + * @return 项目数量 + */ + Long getCheckPlanSubjectCountByPlanId(Long planId); + + /** + * 根据方案编号删除所有项目关联 + * + * @param planId 方案编号 + */ + void deleteByPlanId(Long planId); + + /** + * 获得指定项目的方案项目关联数量 + * + * @param subjectId 项目编号 + * @return 项目关联数量 + */ + Long getCheckPlanSubjectCountBySubjectId(Long subjectId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectServiceImpl.java new file mode 100644 index 000000000..e0aa10a71 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectServiceImpl.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkplan; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo.subject.MesDvCheckPlanSubjectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanSubjectDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.checkplan.MesDvCheckPlanSubjectMapper; +import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 点检保养方案项目 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvCheckPlanSubjectServiceImpl implements MesDvCheckPlanSubjectService { + + @Resource + private MesDvCheckPlanSubjectMapper checkPlanSubjectMapper; + @Resource + @Lazy + private MesDvCheckPlanService checkPlanService; + @Resource + private MesDvSubjectService subjectService; + + @Override + public Long createCheckPlanSubject(MesDvCheckPlanSubjectSaveReqVO createReqVO) { + // 1.1 校验方案草稿状态 + checkPlanService.validateCheckPlanPrepare(createReqVO.getPlanId()); + // 1.2 校验项目存在 + subjectService.validateSubjectExists(createReqVO.getSubjectId()); + // 1.3 校验同一方案下项目不重复 + if (checkPlanSubjectMapper.selectByPlanIdAndSubjectId(createReqVO.getPlanId(), createReqVO.getSubjectId()) != null) { + throw exception(DV_CHECK_PLAN_SUBJECT_DUPLICATE); + } + + // 2. 插入 + MesDvCheckPlanSubjectDO planSubject = BeanUtils.toBean(createReqVO, MesDvCheckPlanSubjectDO.class); + checkPlanSubjectMapper.insert(planSubject); + return planSubject.getId(); + } + + @Override + public void deleteCheckPlanSubject(Long id) { + // 1.1 校验存在 + MesDvCheckPlanSubjectDO existRecord = checkPlanSubjectMapper.selectById(id); + if (existRecord == null) { + throw exception(DV_CHECK_PLAN_SUBJECT_NOT_EXISTS); + } + // 1.2 校验方案草稿状态 + checkPlanService.validateCheckPlanPrepare(existRecord.getPlanId()); + + // 2. 删除 + checkPlanSubjectMapper.deleteById(id); + } + + @Override + public List getCheckPlanSubjectListByPlanId(Long planId) { + return checkPlanSubjectMapper.selectListByPlanId(planId); + } + + @Override + public Long getCheckPlanSubjectCountByPlanId(Long planId) { + return checkPlanSubjectMapper.selectCountByPlanId(planId); + } + + @Override + public void deleteByPlanId(Long planId) { + checkPlanSubjectMapper.deleteByPlanId(planId); + } + + @Override + public Long getCheckPlanSubjectCountBySubjectId(Long subjectId) { + return checkPlanSubjectMapper.selectCountBySubjectId(subjectId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineService.java new file mode 100644 index 000000000..6a09c7c69 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordLineDO; + +import jakarta.validation.Valid; +import java.util.List; + +/** + * MES 设备点检记录明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvCheckRecordLineService { + + /** + * 创建点检记录明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCheckRecordLine(@Valid MesDvCheckRecordLineSaveReqVO createReqVO); + + /** + * 更新点检记录明细 + * + * @param updateReqVO 更新信息 + */ + void updateCheckRecordLine(@Valid MesDvCheckRecordLineSaveReqVO updateReqVO); + + /** + * 删除点检记录明细 + * + * @param id 编号 + */ + void deleteCheckRecordLine(Long id); + + /** + * 根据点检记录编号删除所有明细 + * + * @param recordId 点检记录编号 + */ + void deleteByRecordId(Long recordId); + + /** + * 批量创建点检记录明细 + * + * @param lines 明细列表 + */ + void createCheckRecordLineList(List lines); + + /** + * 校验点检记录明细存在 + * + * @param id 编号 + */ + void validateCheckRecordLineExists(Long id); + + /** + * 获得点检记录明细 + * + * @param id 编号 + * @return 点检记录明细 + */ + MesDvCheckRecordLineDO getCheckRecordLine(Long id); + + /** + * 获得点检记录明细分页 + * + * @param pageReqVO 分页查询 + * @return 点检记录明细分页 + */ + PageResult getCheckRecordLinePage(MesDvCheckRecordLinePageReqVO pageReqVO); + + /** + * 获得指定点检记录的所有明细 + * + * @param recordId 点检记录编号 + * @return 明细列表 + */ + List getCheckRecordLineListByRecordId(Long recordId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineServiceImpl.java new file mode 100644 index 000000000..25f29e199 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineServiceImpl.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line.MesDvCheckRecordLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.checkrecord.MesDvCheckRecordLineMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.DV_CHECK_RECORD_LINE_NOT_EXISTS; + +/** + * MES 设备点检记录明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvCheckRecordLineServiceImpl implements MesDvCheckRecordLineService { + + @Resource + private MesDvCheckRecordLineMapper checkRecordLineMapper; + + @Resource + @Lazy + private MesDvCheckRecordService checkRecordService; + + @Override + public Long createCheckRecordLine(MesDvCheckRecordLineSaveReqVO createReqVO) { + // 1. 校验点检记录存在且为草稿状态 + checkRecordService.validateCheckRecordDraft(createReqVO.getRecordId()); + + // 2. 插入 + MesDvCheckRecordLineDO line = BeanUtils.toBean(createReqVO, MesDvCheckRecordLineDO.class); + checkRecordLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateCheckRecordLine(MesDvCheckRecordLineSaveReqVO updateReqVO) { + // 1.1 校验行存在 + validateCheckRecordLineExists(updateReqVO.getId()); + // 1.2 校验点检记录存在且为草稿状态 + checkRecordService.validateCheckRecordDraft(updateReqVO.getRecordId()); + + // 2. 更新 + MesDvCheckRecordLineDO updateObj = BeanUtils.toBean(updateReqVO, MesDvCheckRecordLineDO.class); + checkRecordLineMapper.updateById(updateObj); + } + + @Override + public void deleteCheckRecordLine(Long id) { + // 1. 校验存在 + // TODO @AI:复用 validateCheckRecordLineExists 方法; + MesDvCheckRecordLineDO line = checkRecordLineMapper.selectById(id); + if (line == null) { + throw exception(DV_CHECK_RECORD_LINE_NOT_EXISTS); + } + + // 2. 校验父记录为草稿状态 + checkRecordService.validateCheckRecordDraft(line.getRecordId()); + // 3. 删除 + checkRecordLineMapper.deleteById(id); + } + + @Override + public void deleteByRecordId(Long recordId) { + checkRecordLineMapper.deleteByRecordId(recordId); + } + + @Override + public void createCheckRecordLineList(List lines) { + checkRecordLineMapper.insertBatch(lines); + } + + @Override + public void validateCheckRecordLineExists(Long id) { + if (checkRecordLineMapper.selectById(id) == null) { + throw exception(DV_CHECK_RECORD_LINE_NOT_EXISTS); + } + } + + @Override + public MesDvCheckRecordLineDO getCheckRecordLine(Long id) { + return checkRecordLineMapper.selectById(id); + } + + @Override + public PageResult getCheckRecordLinePage(MesDvCheckRecordLinePageReqVO pageReqVO) { + return checkRecordLineMapper.selectPage(pageReqVO); + } + + @Override + public List getCheckRecordLineListByRecordId(Long recordId) { + return checkRecordLineMapper.selectListByRecordId(recordId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordService.java new file mode 100644 index 000000000..1a9778e42 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordDO; + +import jakarta.validation.Valid; + +/** + * MES 设备点检记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvCheckRecordService { + + /** + * 创建设备点检记录 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCheckRecord(@Valid MesDvCheckRecordSaveReqVO createReqVO); + + /** + * 更新设备点检记录 + * + * @param updateReqVO 更新信息 + */ + void updateCheckRecord(@Valid MesDvCheckRecordSaveReqVO updateReqVO); + + /** + * 提交点检记录(状态从草稿变为已完成) + * + * @param id 编号 + */ + void submitCheckRecord(Long id); + + /** + * 删除设备点检记录 + * + * @param id 编号 + */ + void deleteCheckRecord(Long id); + + /** + * 校验设备点检记录存在 + * + * @param id 编号 + */ + void validateCheckRecordExists(Long id); + + /** + * 校验点检记录为草稿状态 + * + * @param id 编号 + */ + void validateCheckRecordDraft(Long id); + + /** + * 获得指定设备的点检记录数量 + * + * @param machineryId 设备编号 + * @return 点检记录数量 + */ + Long getCheckRecordCountByMachineryId(Long machineryId); + + /** + * 获得设备点检记录 + * + * @param id 编号 + * @return 设备点检记录 + */ + MesDvCheckRecordDO getCheckRecord(Long id); + + /** + * 获得设备点检记录分页 + * + * @param pageReqVO 分页查询 + * @return 设备点检记录分页 + */ + PageResult getCheckRecordPage(MesDvCheckRecordPageReqVO pageReqVO); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java new file mode 100644 index 000000000..22be2b84f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java @@ -0,0 +1,190 @@ +package cn.iocoder.yudao.module.mes.service.dv.checkrecord; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.MesDvCheckRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanSubjectDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordLineDO; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckRecordStatusEnum; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckResultEnum; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.checkrecord.MesDvCheckRecordMapper; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanSubjectService; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 设备点检记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { + + @Resource + private MesDvCheckRecordMapper checkRecordMapper; + @Resource + @Lazy + private MesDvCheckRecordLineService checkRecordLineService; + @Resource + private MesDvMachineryService machineryService; + @Resource + private MesDvCheckPlanService checkPlanService; + @Resource + private MesDvCheckPlanSubjectService checkPlanSubjectService; + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createCheckRecord(MesDvCheckRecordSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateCheckRecordSave(createReqVO); + + // 2. 插入主记录,状态默认为草稿 + MesDvCheckRecordDO checkRecord = BeanUtils.toBean(createReqVO, MesDvCheckRecordDO.class) + .setStatus(MesDvCheckRecordStatusEnum.DRAFT.getStatus()); + checkRecordMapper.insert(checkRecord); + + // 3. 如果指定了点检计划,自动生成明细行 + if (createReqVO.getPlanId() != null) { + generateCheckRecordLines(checkRecord.getId(), createReqVO.getPlanId()); + } + return checkRecord.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateCheckRecord(MesDvCheckRecordSaveReqVO updateReqVO) { + // 1.1 校验存在 + 状态为草稿 + validateCheckRecordDraft(updateReqVO.getId()); + // 1.2 校验关联数据 + validateCheckRecordSave(updateReqVO); + + // 2. 如果计划变更,删除旧明细并重新生成 + MesDvCheckRecordDO existRecord = checkRecordMapper.selectById(updateReqVO.getId()); + Long oldPlanId = existRecord.getPlanId(); + Long newPlanId = updateReqVO.getPlanId(); + boolean planChanged = ObjUtil.notEqual(oldPlanId, newPlanId); + if (planChanged) { + checkRecordLineService.deleteByRecordId(updateReqVO.getId()); + if (newPlanId != null) { + generateCheckRecordLines(updateReqVO.getId(), newPlanId); + } + } + + // 3. 更新主记录 + MesDvCheckRecordDO updateObj = BeanUtils.toBean(updateReqVO, MesDvCheckRecordDO.class); + checkRecordMapper.updateById(updateObj); + } + + @Override + public void submitCheckRecord(Long id) { + // 1.1 校验状态为草稿 + validateCheckRecordDraft(id); + // 1.2 校验至少有一条明细 + List lines = checkRecordLineService.getCheckRecordLineListByRecordId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(DV_CHECK_RECORD_NO_LINE); + } + + // 2. 状态改为已完成 + MesDvCheckRecordDO updateObj = new MesDvCheckRecordDO() + .setId(id).setStatus(MesDvCheckRecordStatusEnum.FINISHED.getStatus()); + checkRecordMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteCheckRecord(Long id) { + // 1. 校验状态为草稿(已完成不可删除) + validateCheckRecordDraft(id); + + // 2.1 删除主记录 + checkRecordMapper.deleteById(id); + // 2.2 级联删除明细 + checkRecordLineService.deleteByRecordId(id); + } + + @Override + public void validateCheckRecordExists(Long id) { + if (checkRecordMapper.selectById(id) == null) { + throw exception(DV_CHECK_RECORD_NOT_EXISTS); + } + } + + @Override + public Long getCheckRecordCountByMachineryId(Long machineryId) { + return checkRecordMapper.selectCountByMachineryId(machineryId); + } + + @Override + public MesDvCheckRecordDO getCheckRecord(Long id) { + return checkRecordMapper.selectById(id); + } + + @Override + public PageResult getCheckRecordPage(MesDvCheckRecordPageReqVO pageReqVO) { + return checkRecordMapper.selectPage(pageReqVO); + } + + // ==================== 校验方法 ==================== + + @Override + public void validateCheckRecordDraft(Long id) { + MesDvCheckRecordDO record = checkRecordMapper.selectById(id); + if (record == null) { + throw exception(DV_CHECK_RECORD_NOT_EXISTS); + } + if (ObjUtil.notEqual(MesDvCheckRecordStatusEnum.DRAFT.getStatus(), record.getStatus())) { + throw exception(DV_CHECK_RECORD_NOT_DRAFT); + } + } + + private void validateCheckRecordSave(MesDvCheckRecordSaveReqVO reqVO) { + // 校验设备是否存在 + machineryService.validateMachineryExists(reqVO.getMachineryId()); + // 校验点检计划是否存在 + if (reqVO.getPlanId() != null) { + checkPlanService.validateCheckPlanExists(reqVO.getPlanId()); + } + // 校验点检人是否存在 + if (reqVO.getUserId() != null) { + adminUserApi.validateUser(reqVO.getUserId()); + } + } + + /** + * 根据计划自动生成点检项目明细行 + */ + private void generateCheckRecordLines(Long recordId, Long planId) { + List planSubjects = checkPlanSubjectService.getCheckPlanSubjectListByPlanId(planId); + if (CollUtil.isEmpty(planSubjects)) { + return; + } + List lines = new ArrayList<>(planSubjects.size()); + for (MesDvCheckPlanSubjectDO planSubject : planSubjects) { + lines.add(new MesDvCheckRecordLineDO() + .setRecordId(recordId).setSubjectId(planSubject.getSubjectId()) + .setCheckStatus(MesDvCheckResultEnum.NORMAL.getResult())); + } + checkRecordLineService.createCheckRecordLineList(lines); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java new file mode 100644 index 000000000..cc4dac3a8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.module.mes.service.dv.machinery; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachinerySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 设备台账 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvMachineryService { + + /** + * 创建设备 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMachinery(@Valid MesDvMachinerySaveReqVO createReqVO); + + /** + * 更新设备 + * + * @param updateReqVO 更新信息 + */ + void updateMachinery(@Valid MesDvMachinerySaveReqVO updateReqVO); + + /** + * 删除设备 + * + * @param id 编号 + */ + void deleteMachinery(Long id); + + /** + * 获得设备 + * + * @param id 编号 + * @return 设备 + */ + MesDvMachineryDO getMachinery(Long id); + + /** + * 获得设备分页 + * + * @param pageReqVO 分页查询 + * @return 设备分页 + */ + PageResult getMachineryPage(MesDvMachineryPageReqVO pageReqVO); + + /** + * 获得指定设备类型下的设备数量 + * + * @param machineryTypeId 设备类型编号 + * @return 设备数量 + */ + Long getMachineryCountByMachineryTypeId(Long machineryTypeId); + + /** + * 校验设备存在 + * + * @param id 编号 + */ + void validateMachineryExists(Long id); + + /** + * 获得设备列表 + * + * @return 设备列表 + */ + List getMachineryList(); + + /** + * 获得设备列表 + * + * @param ids 编号数组 + * @return 设备列表 + */ + List getMachineryList(Collection ids); + + /** + * 获得设备 Map + * + * @param ids 编号数组 + * @return 设备 Map + */ + default Map getMachineryMap(Collection ids) { + return convertMap(getMachineryList(ids), MesDvMachineryDO::getId); + } + + /** + * 导入设备列表 + * + * @param importMachineryList 导入设备列表 + * @param updateSupport 是否支持更新 + * @return 导入结果 + */ + MesDvMachineryImportRespVO importMachineryList(List importMachineryList, + boolean updateSupport); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java new file mode 100644 index 000000000..9da51df85 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java @@ -0,0 +1,274 @@ +package cn.iocoder.yudao.module.mes.service.dv.machinery; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachinerySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.machinery.MesDvMachineryMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanMachineryService; +import cn.iocoder.yudao.module.mes.service.dv.checkrecord.MesDvCheckRecordService; +import cn.iocoder.yudao.module.mes.service.dv.maintenrecord.MesDvMaintenRecordService; +import cn.iocoder.yudao.module.mes.service.dv.repair.MesDvRepairService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkshopService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 设备台账 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvMachineryServiceImpl implements MesDvMachineryService { + + @Resource + private MesDvMachineryMapper machineryMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private MesDvMachineryTypeService machineryTypeService; + + @Resource + @Lazy + private MesMdWorkshopService workshopService; + + @Resource + private MesWmBarcodeService barcodeService; + + @Resource + @Lazy + private MesDvCheckPlanMachineryService checkPlanMachineryService; + + @Resource + @Lazy + private MesDvCheckRecordService checkRecordService; + + @Resource + @Lazy + private MesDvMaintenRecordService maintenRecordService; + + @Resource + @Lazy + private MesDvRepairService repairService; + + @Override + public Long createMachinery(MesDvMachinerySaveReqVO createReqVO) { + // 校验设备类型存在 + machineryTypeService.getMachineryType(createReqVO.getMachineryTypeId()); + // 校验车间存在 + workshopService.getWorkshop(createReqVO.getWorkshopId()); + // 校验编码唯一 + validateMachineryCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesDvMachineryDO machinery = BeanUtils.toBean(createReqVO, MesDvMachineryDO.class); + machineryMapper.insert(machinery); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.MACHINERY.getValue(), + machinery.getId(), machinery.getCode(), machinery.getName()); + return machinery.getId(); + } + + @Override + public void updateMachinery(MesDvMachinerySaveReqVO updateReqVO) { + // 校验存在 + validateMachineryExists(updateReqVO.getId()); + // 校验设备类型存在 + machineryTypeService.getMachineryType(updateReqVO.getMachineryTypeId()); + // 校验车间存在 + workshopService.getWorkshop(updateReqVO.getWorkshopId()); + // 校验编码唯一 + validateMachineryCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesDvMachineryDO updateObj = BeanUtils.toBean(updateReqVO, MesDvMachineryDO.class); + machineryMapper.updateById(updateObj); + } + + @Override + public void deleteMachinery(Long id) { + // 校验存在 + validateMachineryExists(id); + // 校验关联数据 + if (checkPlanMachineryService.getCheckPlanMachineryCountByMachineryId(id) > 0) { + throw exception(DV_MACHINERY_HAS_CHECK_PLAN); + } + if (checkRecordService.getCheckRecordCountByMachineryId(id) > 0) { + throw exception(DV_MACHINERY_HAS_CHECK_RECORD); + } + if (maintenRecordService.getMaintenRecordCountByMachineryId(id) > 0) { + throw exception(DV_MACHINERY_HAS_MAINTEN_RECORD); + } + if (repairService.getRepairCountByMachineryId(id) > 0) { + throw exception(DV_MACHINERY_HAS_REPAIR); + } + + // 删除 + machineryMapper.deleteById(id); + } + + @Override + public void validateMachineryExists(Long id) { + if (machineryMapper.selectById(id) == null) { + throw exception(DV_MACHINERY_NOT_EXISTS); + } + } + + private void validateMachineryCodeUnique(Long id, String code) { + if (code == null) { + return; + } + MesDvMachineryDO machinery = machineryMapper.selectByCode(code); + if (machinery == null) { + return; + } + if (ObjUtil.notEqual(machinery.getId(), id)) { + throw exception(DV_MACHINERY_CODE_DUPLICATE); + } + } + + @Override + public MesDvMachineryDO getMachinery(Long id) { + return machineryMapper.selectById(id); + } + + @Override + public PageResult getMachineryPage(MesDvMachineryPageReqVO pageReqVO) { + // 处理设备类型树形查询:选择父类型时,同时查询所有子类型下的设备 + if (pageReqVO.getMachineryTypeId() != null) { + List children = machineryTypeService.getMachineryTypeChildrenList( + pageReqVO.getMachineryTypeId()); + Set typeIds = new HashSet<>(); + typeIds.add(pageReqVO.getMachineryTypeId()); + children.forEach(child -> typeIds.add(child.getId())); + pageReqVO.setMachineryTypeIds(typeIds); + } + return machineryMapper.selectPage(pageReqVO); + } + + @Override + public Long getMachineryCountByMachineryTypeId(Long machineryTypeId) { + return machineryMapper.selectCountByMachineryTypeId(machineryTypeId); + } + + @Override + public List getMachineryList() { + return machineryMapper.selectList(); + } + + @Override + public List getMachineryList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return machineryMapper.selectByIds(ids); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MesDvMachineryImportRespVO importMachineryList(List importMachineryList, + boolean updateSupport) { + // 1. 参数校验 + if (CollUtil.isEmpty(importMachineryList)) { + throw exception(DV_MACHINERY_IMPORT_LIST_IS_EMPTY); + } + + // 2. 批量加载设备类型和车间,构建编码到实体的映射 + List allTypes = machineryTypeService.getMachineryTypeList( + new cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeListReqVO()); + Map typeCodeMap = allTypes.stream() + .collect(Collectors.toMap(MesDvMachineryTypeDO::getCode, t -> t, (a, b) -> a)); + List allWorkshops = workshopService.getWorkshopListByStatus( + cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus()); + Map workshopCodeMap = allWorkshops.stream() + .collect(Collectors.toMap(MesMdWorkshopDO::getCode, w -> w, (a, b) -> a)); + + // 3. 遍历,逐个创建 or 更新 + MesDvMachineryImportRespVO respVO = MesDvMachineryImportRespVO.builder() + .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>()) + .failureCodes(new LinkedHashMap<>()).build(); + AtomicInteger index = new AtomicInteger(1); + importMachineryList.forEach(importItem -> { + int currentIndex = index.getAndIncrement(); + // 3.1 校验必填字段 + String key = StrUtil.blankToDefault(importItem.getCode(), "第 " + currentIndex + " 行"); + if (StrUtil.isBlank(importItem.getCode())) { + respVO.getFailureCodes().put(key, "设备编码不能为空"); + return; + } + if (StrUtil.isBlank(importItem.getName())) { + respVO.getFailureCodes().put(key, "设备名称不能为空"); + return; + } + // 3.2 校验设备类型编码 + if (StrUtil.isBlank(importItem.getMachineryTypeCode())) { + respVO.getFailureCodes().put(key, "设备类型编码不能为空"); + return; + } + MesDvMachineryTypeDO machineryType = typeCodeMap.get(importItem.getMachineryTypeCode()); + if (machineryType == null) { + respVO.getFailureCodes().put(key, "设备类型编码[" + importItem.getMachineryTypeCode() + "]不存在"); + return; + } + // 3.3 校验车间编码 + if (StrUtil.isBlank(importItem.getWorkshopCode())) { + respVO.getFailureCodes().put(key, "车间编码不能为空"); + return; + } + MesMdWorkshopDO workshop = workshopCodeMap.get(importItem.getWorkshopCode()); + if (workshop == null) { + respVO.getFailureCodes().put(key, "车间编码[" + importItem.getWorkshopCode() + "]不存在"); + return; + } + + // 3.4 判断:创建 or 更新 + MesDvMachineryDO existMachinery = machineryMapper.selectByCode(importItem.getCode()); + if (existMachinery == null) { + // 3.4.1 创建 + MesDvMachineryDO machinery = BeanUtils.toBean(importItem, MesDvMachineryDO.class); + machinery.setMachineryTypeId(machineryType.getId()); + machinery.setWorkshopId(workshop.getId()); + machineryMapper.insert(machinery); + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.MACHINERY.getValue(), + machinery.getId(), machinery.getCode(), machinery.getName()); + respVO.getCreateCodes().add(importItem.getCode()); + } else if (updateSupport) { + // 3.4.2 更新 + MesDvMachineryDO updateObj = BeanUtils.toBean(importItem, MesDvMachineryDO.class); + updateObj.setId(existMachinery.getId()); + updateObj.setMachineryTypeId(machineryType.getId()); + updateObj.setWorkshopId(workshop.getId()); + machineryMapper.updateById(updateObj); + respVO.getUpdateCodes().add(importItem.getCode()); + } else { + // 不支持更新 + respVO.getFailureCodes().put(key, "设备编码已存在"); + } + }); + return respVO; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryTypeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryTypeService.java new file mode 100644 index 000000000..0f63253e5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryTypeService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.service.dv.machinery; + +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 设备类型 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvMachineryTypeService { + + /** + * 创建设备类型 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMachineryType(@Valid MesDvMachineryTypeSaveReqVO createReqVO); + + /** + * 更新设备类型 + * + * @param updateReqVO 更新信息 + */ + void updateMachineryType(@Valid MesDvMachineryTypeSaveReqVO updateReqVO); + + /** + * 删除设备类型 + * + * @param id 编号 + */ + void deleteMachineryType(Long id); + + /** + * 获得设备类型 + * + * @param id 编号 + * @return 设备类型 + */ + MesDvMachineryTypeDO getMachineryType(Long id); + + /** + * 获得设备类型列表 + * + * @param listReqVO 列表查询 + * @return 设备类型列表 + */ + List getMachineryTypeList(MesDvMachineryTypeListReqVO listReqVO); + + /** + * 获得设备类型列表 + * + * @param ids 编号数组 + * @return 设备类型列表 + */ + List getMachineryTypeList(Collection ids); + + /** + * 获得设备类型 Map + * + * @param ids 编号数组 + * @return 设备类型 Map + */ + default Map getMachineryTypeMap(Collection ids) { + return convertMap(getMachineryTypeList(ids), MesDvMachineryTypeDO::getId); + } + + /** + * 获得指定父类型下的所有子类型(递归) + * + * @param parentId 父类型编号 + * @return 子类型列表 + */ + List getMachineryTypeChildrenList(Long parentId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryTypeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryTypeServiceImpl.java new file mode 100644 index 000000000..aa6eb839e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryTypeServiceImpl.java @@ -0,0 +1,191 @@ +package cn.iocoder.yudao.module.mes.service.dv.machinery; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryTypeDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.machinery.MesDvMachineryTypeMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 设备类型 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvMachineryTypeServiceImpl implements MesDvMachineryTypeService { + + @Resource + private MesDvMachineryTypeMapper machineryTypeMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private MesDvMachineryService machineryService; + + @Override + public Long createMachineryType(MesDvMachineryTypeSaveReqVO createReqVO) { + // 校验 + validateMachineryTypeSaveData(createReqVO); + + // 插入 + MesDvMachineryTypeDO machineryType = BeanUtils.toBean(createReqVO, MesDvMachineryTypeDO.class); + machineryTypeMapper.insert(machineryType); + return machineryType.getId(); + } + + @Override + public void updateMachineryType(MesDvMachineryTypeSaveReqVO updateReqVO) { + // 校验 + validateMachineryTypeSaveData(updateReqVO); + + // 更新 + MesDvMachineryTypeDO updateObj = BeanUtils.toBean(updateReqVO, MesDvMachineryTypeDO.class); + machineryTypeMapper.updateById(updateObj); + } + + @Override + public void deleteMachineryType(Long id) { + // 1.1 校验存在 + validateMachineryTypeExists(id); + // 1.2 校验是否有子类型 + if (machineryTypeMapper.selectCountByParentId(id) > 0) { + throw exception(DV_MACHINERY_TYPE_EXITS_CHILDREN); + } + // 1.3 校验是否有设备 + if (machineryService.getMachineryCountByMachineryTypeId(id) > 0) { + throw exception(DV_MACHINERY_TYPE_HAS_MACHINERY); + } + + // 2. 删除 + machineryTypeMapper.deleteById(id); + } + + private void validateMachineryTypeSaveData(MesDvMachineryTypeSaveReqVO saveReqVO) { + if (saveReqVO.getId() != null) { + validateMachineryTypeExists(saveReqVO.getId()); + } + // 校验父级节点有效性 + validateParentMachineryType(saveReqVO.getId(), saveReqVO.getParentId()); + // 校验类型名称唯一性 + validateMachineryTypeNameUnique(saveReqVO.getId(), saveReqVO.getParentId(), saveReqVO.getName()); + // 校验类型编码唯一性 + validateMachineryTypeCodeUnique(saveReqVO.getId(), saveReqVO.getParentId(), saveReqVO.getCode()); + } + + private void validateMachineryTypeExists(Long id) { + if (machineryTypeMapper.selectById(id) == null) { + throw exception(DV_MACHINERY_TYPE_NOT_EXISTS); + } + } + + private void validateParentMachineryType(Long id, Long parentId) { + if (parentId == null || MesDvMachineryTypeDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父类型 + if (Objects.equals(id, parentId)) { + throw exception(DV_MACHINERY_TYPE_PARENT_ERROR); + } + // 2. 父类型不存在 + MesDvMachineryTypeDO parentType = machineryTypeMapper.selectById(parentId); + if (parentType == null) { + throw exception(DV_MACHINERY_TYPE_PARENT_NOT_EXITS); + } + // 3. 递归校验父类型,如果父类型是自己的子类型,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentType.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(DV_MACHINERY_TYPE_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父类型 + if (parentId == null || MesDvMachineryTypeDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentType = machineryTypeMapper.selectById(parentId); + if (parentType == null) { + break; + } + } + } + + private void validateMachineryTypeNameUnique(Long id, Long parentId, String name) { + MesDvMachineryTypeDO machineryType = machineryTypeMapper.selectByParentIdAndName(parentId, name); + if (machineryType == null) { + return; + } + if (ObjUtil.notEqual(machineryType.getId(), id)) { + throw exception(DV_MACHINERY_TYPE_NAME_DUPLICATE); + } + } + + private void validateMachineryTypeCodeUnique(Long id, Long parentId, String code) { + MesDvMachineryTypeDO machineryType = machineryTypeMapper.selectByCode(code); + if (machineryType == null) { + return; + } + if (ObjUtil.notEqual(machineryType.getId(), id)) { + throw exception(DV_MACHINERY_TYPE_CODE_DUPLICATE); + } + } + + @Override + public MesDvMachineryTypeDO getMachineryType(Long id) { + return machineryTypeMapper.selectById(id); + } + + @Override + public List getMachineryTypeList(MesDvMachineryTypeListReqVO listReqVO) { + return machineryTypeMapper.selectList(listReqVO); + } + + @Override + public List getMachineryTypeList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return machineryTypeMapper.selectByIds(ids); + } + + @Override + public List getMachineryTypeChildrenList(Long parentId) { + List allList = machineryTypeMapper.selectList(); // 类型总量小,全量查 + // 1. 构建 parentId -> children 的 Map(类似 menu 的 treeNodeMap 思路) + Map> parentChildrenMap = new LinkedHashMap<>(); + allList.forEach(type -> parentChildrenMap + .computeIfAbsent(type.getParentId(), k -> new ArrayList<>()).add(type)); + // 2. 收集所有后代节点 + List result = new ArrayList<>(); + List parentIds = new ArrayList<>(); + parentIds.add(parentId); + for (int i = 0; i < Short.MAX_VALUE; i++) { + if (i >= parentIds.size()) { + break; + } + List children = parentChildrenMap.get(parentIds.get(i)); + if (children == null) { + continue; + } + for (MesDvMachineryTypeDO child : children) { + result.add(child); + parentIds.add(child.getId()); + } + } + return result; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineService.java new file mode 100644 index 000000000..30848bce8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineService.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.service.dv.maintenrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordLineDO; + +import jakarta.validation.Valid; +import java.util.List; + +/** + * 设备保养记录明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvMaintenRecordLineService { + + /** + * 创建设备保养记录明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMaintenRecordLine(@Valid MesDvMaintenRecordLineSaveReqVO createReqVO); + + /** + * 更新设备保养记录明细 + * + * @param updateReqVO 更新信息 + */ + void updateMaintenRecordLine(@Valid MesDvMaintenRecordLineSaveReqVO updateReqVO); + + /** + * 删除设备保养记录明细 + * + * @param id 编号 + */ + void deleteMaintenRecordLine(Long id); + + /** + * 获得设备保养记录明细 + * + * @param id 编号 + * @return 设备保养记录明细 + */ + MesDvMaintenRecordLineDO getMaintenRecordLine(Long id); + + /** + * 获得设备保养记录明细分页 + * + * @param pageReqVO 分页查询 + * @return 设备保养记录明细分页 + */ + PageResult getMaintenRecordLinePage(MesDvMaintenRecordLinePageReqVO pageReqVO); + + /** + * 获得指定保养记录的明细列表 + * + * @param recordId 保养记录编号 + * @return 明细列表 + */ + List getMaintenRecordLineListByRecordId(Long recordId); + + /** + * 根据保养记录编号删除所有明细 + * + * @param recordId 保养记录编号 + */ + void deleteMaintenRecordLineByRecordId(Long recordId); + +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineServiceImpl.java new file mode 100644 index 000000000..01bb05e94 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineServiceImpl.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.mes.service.dv.maintenrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line.MesDvMaintenRecordLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.maintenrecord.MesDvMaintenRecordLineMapper; +import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 设备保养记录明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvMaintenRecordLineServiceImpl implements MesDvMaintenRecordLineService { + + @Resource + private MesDvMaintenRecordLineMapper maintenRecordLineMapper; + + @Resource + @Lazy + private MesDvMaintenRecordService maintenRecordService; + @Resource + private MesDvSubjectService subjectService; + + @Override + public Long createMaintenRecordLine(MesDvMaintenRecordLineSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateMaintenRecordLineRelation(createReqVO); + + // 2. 插入 + MesDvMaintenRecordLineDO maintenRecordLine = BeanUtils.toBean(createReqVO, MesDvMaintenRecordLineDO.class); + maintenRecordLineMapper.insert(maintenRecordLine); + return maintenRecordLine.getId(); + } + + @Override + public void updateMaintenRecordLine(MesDvMaintenRecordLineSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateMaintenRecordLineExists(updateReqVO.getId()); + // 1.2 校验关联数据 + validateMaintenRecordLineRelation(updateReqVO); + + // 2. 更新 + MesDvMaintenRecordLineDO updateObj = BeanUtils.toBean(updateReqVO, MesDvMaintenRecordLineDO.class); + maintenRecordLineMapper.updateById(updateObj); + } + + @Override + public void deleteMaintenRecordLine(Long id) { + // 1.1 校验存在 + MesDvMaintenRecordLineDO line = validateMaintenRecordLineExists(id); + // 1.2 校验保养记录为草稿状态 + maintenRecordService.validateMaintenRecordDraft(line.getRecordId()); + + // 2. 删除 + maintenRecordLineMapper.deleteById(id); + } + + private void validateMaintenRecordLineRelation(MesDvMaintenRecordLineSaveReqVO reqVO) { + // 校验保养记录为草稿状态 + maintenRecordService.validateMaintenRecordDraft(reqVO.getRecordId()); + // 校验保养项目是否存在 + subjectService.validateSubjectExists(reqVO.getSubjectId()); + } + + private MesDvMaintenRecordLineDO validateMaintenRecordLineExists(Long id) { + MesDvMaintenRecordLineDO maintenRecordLine = maintenRecordLineMapper.selectById(id); + if (maintenRecordLine == null) { + throw exception(MAINTEN_RECORD_LINE_NOT_EXISTS); + } + return maintenRecordLine; + } + + @Override + public MesDvMaintenRecordLineDO getMaintenRecordLine(Long id) { + return maintenRecordLineMapper.selectById(id); + } + + @Override + public PageResult getMaintenRecordLinePage(MesDvMaintenRecordLinePageReqVO pageReqVO) { + return maintenRecordLineMapper.selectPage(pageReqVO); + } + + @Override + public List getMaintenRecordLineListByRecordId(Long recordId) { + return maintenRecordLineMapper.selectListByRecordId(recordId); + } + + @Override + public void deleteMaintenRecordLineByRecordId(Long recordId) { + maintenRecordLineMapper.deleteByRecordId(recordId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordService.java new file mode 100644 index 000000000..e1747822b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.service.dv.maintenrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordDO; + +import jakarta.validation.Valid; + +/** + * 设备保养记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvMaintenRecordService { + + /** + * 创建设备保养记录 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMaintenRecord(@Valid MesDvMaintenRecordSaveReqVO createReqVO); + + /** + * 更新设备保养记录 + * + * @param updateReqVO 更新信息 + */ + void updateMaintenRecord(@Valid MesDvMaintenRecordSaveReqVO updateReqVO); + + /** + * 提交设备保养记录(草稿→已提交) + * + * @param id 编号 + */ + void submitMaintenRecord(Long id); + + /** + * 删除设备保养记录 + * + * @param id 编号 + */ + void deleteMaintenRecord(Long id); + + /** + * 校验设备保养记录存在 + * + * @param id 编号 + */ + void validateMaintenRecordExists(Long id); + + /** + * 校验设备保养记录是否为草稿状态 + * + * @param id 编号 + * @return 保养记录 + */ + MesDvMaintenRecordDO validateMaintenRecordDraft(Long id); + + /** + * 获得指定设备的保养记录数量 + * + * @param machineryId 设备编号 + * @return 保养记录数量 + */ + Long getMaintenRecordCountByMachineryId(Long machineryId); + + /** + * 获得设备保养记录 + * + * @param id 编号 + * @return 设备保养记录 + */ + MesDvMaintenRecordDO getMaintenRecord(Long id); + + /** + * 获得设备保养记录分页 + * + * @param pageReqVO 分页查询 + * @return 设备保养记录分页 + */ + PageResult getMaintenRecordPage(MesDvMaintenRecordPageReqVO pageReqVO); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java new file mode 100644 index 000000000..afb44b91d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.module.mes.service.dv.maintenrecord; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.MesDvMaintenRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.maintenrecord.MesDvMaintenRecordMapper; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvMaintenRecordStatusEnum; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 设备保养记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvMaintenRecordServiceImpl implements MesDvMaintenRecordService { + + @Resource + private MesDvMaintenRecordMapper maintenRecordMapper; + @Resource + @Lazy + private MesDvMaintenRecordLineService maintenRecordLineService; + @Resource + private MesDvMachineryService machineryService; + @Resource + private MesDvCheckPlanService checkPlanService; + + @Override + public Long createMaintenRecord(MesDvMaintenRecordSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateMaintenRecordRelation(createReqVO); + + // 2. 插入 + MesDvMaintenRecordDO maintenRecord = BeanUtils.toBean(createReqVO, MesDvMaintenRecordDO.class); + maintenRecord.setStatus(MesDvMaintenRecordStatusEnum.PREPARE.getStatus()); + maintenRecordMapper.insert(maintenRecord); + return maintenRecord.getId(); + } + + @Override + public void updateMaintenRecord(MesDvMaintenRecordSaveReqVO updateReqVO) { + // 1.1 校验存在,且状态为草稿 + validateMaintenRecordDraft(updateReqVO.getId()); + // 1.2 校验关联数据 + validateMaintenRecordRelation(updateReqVO); + + // 2. 更新 + MesDvMaintenRecordDO updateObj = BeanUtils.toBean(updateReqVO, MesDvMaintenRecordDO.class); + maintenRecordMapper.updateById(updateObj); + } + + @Override + public void submitMaintenRecord(Long id) { + // 1.1 校验状态为草稿 + validateMaintenRecordDraft(id); + // 1.2 校验至少有一条明细 + List lines = maintenRecordLineService.getMaintenRecordLineListByRecordId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(MAINTEN_RECORD_NO_LINE); + } + + // 2. 状态改为已提交 + MesDvMaintenRecordDO updateObj = new MesDvMaintenRecordDO(); + updateObj.setId(id); + updateObj.setStatus(MesDvMaintenRecordStatusEnum.SUBMITTED.getStatus()); + maintenRecordMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteMaintenRecord(Long id) { + // 校验存在,且状态为草稿 + validateMaintenRecordDraft(id); + + // 删除 + maintenRecordMapper.deleteById(id); + // 级联删除子表 + maintenRecordLineService.deleteMaintenRecordLineByRecordId(id); + } + + private void validateMaintenRecordRelation(MesDvMaintenRecordSaveReqVO reqVO) { + // 校验设备是否存在 + machineryService.validateMachineryExists(reqVO.getMachineryId()); + // 校验保养计划是否存在 + if (reqVO.getPlanId() != null) { + checkPlanService.validateCheckPlanExists(reqVO.getPlanId()); + } + } + + @Override + public void validateMaintenRecordExists(Long id) { + if (maintenRecordMapper.selectById(id) == null) { + throw exception(MAINTEN_RECORD_NOT_EXISTS); + } + } + + @Override + public Long getMaintenRecordCountByMachineryId(Long machineryId) { + return maintenRecordMapper.selectCountByMachineryId(machineryId); + } + + @Override + public MesDvMaintenRecordDO validateMaintenRecordDraft(Long id) { + MesDvMaintenRecordDO record = maintenRecordMapper.selectById(id); + if (record == null) { + throw exception(MAINTEN_RECORD_NOT_EXISTS); + } + if (ObjUtil.notEqual(MesDvMaintenRecordStatusEnum.PREPARE.getStatus(), record.getStatus())) { + throw exception(MAINTEN_RECORD_NOT_DRAFT); + } + return record; + } + + @Override + public MesDvMaintenRecordDO getMaintenRecord(Long id) { + return maintenRecordMapper.selectById(id); + } + + @Override + public PageResult getMaintenRecordPage(MesDvMaintenRecordPageReqVO pageReqVO) { + return maintenRecordMapper.selectPage(pageReqVO); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineService.java new file mode 100644 index 000000000..5fdb0e8dc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineService.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.mes.service.dv.repair; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairLineDO; + +import jakarta.validation.Valid; + +/** + * MES 维修工单行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvRepairLineService { + + /** + * 创建维修工单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createRepairLine(@Valid MesDvRepairLineSaveReqVO createReqVO); + + /** + * 更新维修工单行 + * + * @param updateReqVO 更新信息 + */ + void updateRepairLine(@Valid MesDvRepairLineSaveReqVO updateReqVO); + + /** + * 删除维修工单行 + * + * @param id 编号 + */ + void deleteRepairLine(Long id); + + /** + * 获得维修工单行 + * + * @param id 编号 + * @return 维修工单行 + */ + MesDvRepairLineDO getRepairLine(Long id); + + /** + * 获得维修工单行分页 + * + * @param pageReqVO 分页查询 + * @return 维修工单行分页 + */ + PageResult getRepairLinePage(MesDvRepairLinePageReqVO pageReqVO); + + /** + * 根据维修工单编号删除所有行 + * + * @param repairId 维修工单编号 + */ + void deleteByRepairId(Long repairId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineServiceImpl.java new file mode 100644 index 000000000..09ee904c6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineServiceImpl.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.mes.service.dv.repair; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line.MesDvRepairLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.repair.MesDvRepairLineMapper; +import cn.iocoder.yudao.module.mes.service.dv.subject.MesDvSubjectService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 维修工单行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvRepairLineServiceImpl implements MesDvRepairLineService { + + @Resource + private MesDvRepairLineMapper repairLineMapper; + + @Resource + @Lazy + private MesDvRepairServiceImpl repairService; + @Resource + private MesDvSubjectService subjectService; + + @Override + public Long createRepairLine(MesDvRepairLineSaveReqVO createReqVO) { + // 1.1 校验关联数据 + validateRepairLineRelation(createReqVO); + // 1.2 校验维修工单为草稿状态 + repairService.validateRepairPrepare(createReqVO.getRepairId()); + + // 2. 插入 + MesDvRepairLineDO repairLine = BeanUtils.toBean(createReqVO, MesDvRepairLineDO.class); + repairLineMapper.insert(repairLine); + return repairLine.getId(); + } + + @Override + public void updateRepairLine(MesDvRepairLineSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateRepairLineExists(updateReqVO.getId()); + // 1.2 校验关联数据 + validateRepairLineRelation(updateReqVO); + // 1.3 校验维修工单为草稿状态 + repairService.validateRepairPrepare(updateReqVO.getRepairId()); + + // 2. 更新 + MesDvRepairLineDO updateObj = BeanUtils.toBean(updateReqVO, MesDvRepairLineDO.class); + repairLineMapper.updateById(updateObj); + } + + @Override + public void deleteRepairLine(Long id) { + // 1.1 校验存在 + MesDvRepairLineDO line = repairLineMapper.selectById(id); + if (line == null) { + throw exception(DV_REPAIR_LINE_NOT_EXISTS); + } + // 1.2 校验维修工单为草稿状态 + repairService.validateRepairPrepare(line.getRepairId()); + + // 2. 删除 + repairLineMapper.deleteById(id); + } + + private void validateRepairLineRelation(MesDvRepairLineSaveReqVO reqVO) { + // 校验维修工单是否存在 + repairService.validateRepairExists(reqVO.getRepairId()); + // 校验点检保养项目是否存在(可选) + if (reqVO.getSubjectId() != null) { + subjectService.validateSubjectExists(reqVO.getSubjectId()); + } + } + + private void validateRepairLineExists(Long id) { + if (repairLineMapper.selectById(id) == null) { + throw exception(DV_REPAIR_LINE_NOT_EXISTS); + } + } + + @Override + public MesDvRepairLineDO getRepairLine(Long id) { + return repairLineMapper.selectById(id); + } + + @Override + public PageResult getRepairLinePage(MesDvRepairLinePageReqVO pageReqVO) { + return repairLineMapper.selectPage(pageReqVO); + } + + @Override + public void deleteByRepairId(Long repairId) { + repairLineMapper.deleteByRepairId(repairId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairService.java new file mode 100644 index 000000000..8e002a2e6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairService.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.mes.service.dv.repair; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairConfirmReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairDO; +import jakarta.validation.Valid; + +/** + * MES 维修工单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvRepairService { + + /** + * 创建维修工单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createRepair(@Valid MesDvRepairSaveReqVO createReqVO); + + /** + * 更新维修工单 + * + * @param updateReqVO 更新信息 + */ + void updateRepair(@Valid MesDvRepairSaveReqVO updateReqVO); + + /** + * 删除维修工单 + * + * @param id 编号 + */ + void deleteRepair(Long id); + + /** + * 校验维修工单是否存在 + * + * @param id 编号 + * @return 维修工单 + */ + MesDvRepairDO validateRepairExists(Long id); + + /** + * 获得指定设备的维修工单数量 + * + * @param machineryId 设备编号 + * @return 维修工单数量 + */ + Long getRepairCountByMachineryId(Long machineryId); + + /** + * 获得维修工单 + * + * @param id 编号 + * @return 维修工单 + */ + MesDvRepairDO getRepair(Long id); + + /** + * 获得维修工单分页 + * + * @param pageReqVO 分页查询 + * @return 维修工单分页 + */ + PageResult getRepairPage(MesDvRepairPageReqVO pageReqVO); + + /** + * 提交维修工单(草稿→维修中) + * + * @param id 编号 + */ + void submitRepair(Long id, Long userId); + + /** + * 确认维修完成(维修中→待验收) + * + * @param confirmReqVO 确认信息 + */ + void confirmRepair(@Valid MesDvRepairConfirmReqVO confirmReqVO); + + /** + * 完成验收(待验收→已确认) + * + * @param id 编号 + * @param result 验收结果 + * @param userId 当前登录用户编号 + */ + void finishRepair(Long id, Integer result, Long userId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairServiceImpl.java new file mode 100644 index 000000000..ea4d90a68 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairServiceImpl.java @@ -0,0 +1,173 @@ +package cn.iocoder.yudao.module.mes.service.dv.repair; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.repair.MesDvRepairDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.repair.MesDvRepairMapper; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvRepairStatusEnum; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 维修工单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvRepairServiceImpl implements MesDvRepairService { + + @Resource + private MesDvRepairMapper repairMapper; + + @Resource + private MesDvRepairLineService repairLineService; + @Resource + private MesDvMachineryService machineryService; + + @Override + public Long createRepair(MesDvRepairSaveReqVO createReqVO) { + // 1. 校验保存数据 + validateSaveData(createReqVO); + + // 2. 插入 + MesDvRepairDO repair = BeanUtils.toBean(createReqVO, MesDvRepairDO.class); + repair.setStatus(MesDvRepairStatusEnum.PREPARE.getStatus()); + repairMapper.insert(repair); + return repair.getId(); + } + + @Override + public void updateRepair(MesDvRepairSaveReqVO updateReqVO) { + // 1.1 校验存在,且状态为草稿 + validateRepairPrepare(updateReqVO.getId()); + // 1.2 校验保存数据 + validateSaveData(updateReqVO); + + // 2. 更新 + MesDvRepairDO updateObj = BeanUtils.toBean(updateReqVO, MesDvRepairDO.class); + repairMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteRepair(Long id) { + // 校验存在,且状态为草稿 + validateRepairPrepare(id); + + // 删除 + repairMapper.deleteById(id); + // 级联删除子表 + repairLineService.deleteByRepairId(id); + } + + /** + * 校验保存时的关联数据 + */ + private void validateSaveData(MesDvRepairSaveReqVO reqVO) { + // 校验编码唯一 + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验设备存在 + machineryService.validateMachineryExists(reqVO.getMachineryId()); + } + + private void validateCodeUnique(Long id, String code) { + if (code == null) { + return; + } + MesDvRepairDO repair = repairMapper.selectByCode(code); + if (repair == null) { + return; + } + if (ObjUtil.notEqual(id, repair.getId())) { + throw exception(DV_REPAIR_CODE_DUPLICATE); + } + } + + @Override + public MesDvRepairDO validateRepairExists(Long id) { + MesDvRepairDO repair = repairMapper.selectById(id); + if (repair == null) { + throw exception(DV_REPAIR_NOT_EXISTS); + } + return repair; + } + + @Override + public Long getRepairCountByMachineryId(Long machineryId) { + return repairMapper.selectCountByMachineryId(machineryId); + } + + /** + * 校验维修工单是否为草稿状态 + * + * @param id 编号 + * @return 维修工单 + */ + public MesDvRepairDO validateRepairPrepare(Long id) { + MesDvRepairDO repair = validateRepairExists(id); + if (ObjUtil.notEqual(MesDvRepairStatusEnum.PREPARE.getStatus(), repair.getStatus())) { + throw exception(DV_REPAIR_NOT_PREPARE); + } + return repair; + } + + @Override + public MesDvRepairDO getRepair(Long id) { + return repairMapper.selectById(id); + } + + @Override + public PageResult getRepairPage(MesDvRepairPageReqVO pageReqVO) { + return repairMapper.selectPage(pageReqVO); + } + + @Override + public void submitRepair(Long id, Long userId) { + // 1. 校验存在,且状态为草稿 + validateRepairPrepare(id); + + // 2. 更新状态为维修中,设置维修人 + repairMapper.updateById(new MesDvRepairDO().setId(id) + .setStatus(MesDvRepairStatusEnum.CONFIRMED.getStatus()).setAcceptedUserId(userId)); + } + + @Override + public void confirmRepair(cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.MesDvRepairConfirmReqVO confirmReqVO) { + // 1. 校验存在,且状态为维修中 + MesDvRepairDO repair = validateRepairExists(confirmReqVO.getId()); + if (ObjUtil.notEqual(MesDvRepairStatusEnum.CONFIRMED.getStatus(), repair.getStatus())) { + throw exception(DV_REPAIR_NOT_CONFIRMED); + } + + // 2. 更新状态为待验收,设置维修完成日期 + repairMapper.updateById(new MesDvRepairDO().setId(confirmReqVO.getId()) + .setStatus(MesDvRepairStatusEnum.APPROVING.getStatus()).setFinishDate(confirmReqVO.getFinishDate())); + } + + @Override + public void finishRepair(Long id, Integer result, Long userId) { + // 1. 校验存在,且状态为待验收 + MesDvRepairDO repair = validateRepairExists(id); + if (ObjUtil.notEqual(MesDvRepairStatusEnum.APPROVING.getStatus(), repair.getStatus())) { + throw exception(DV_REPAIR_NOT_APPROVING); + } + + // 2. 更新状态为已确认,设置验收结果、验收人和验收日期 + repairMapper.updateById(new MesDvRepairDO().setId(id) + .setStatus(MesDvRepairStatusEnum.FINISHED.getStatus()).setResult(result) + .setConfirmUserId(userId).setConfirmDate(LocalDateTime.now())); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectService.java new file mode 100644 index 000000000..c2c613ebd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectService.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.mes.service.dv.subject; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 点检保养项目 Service 接口 + * + * @author 芋道源码 + */ +public interface MesDvSubjectService { + + /** + * 创建点检保养项目 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSubject(@Valid MesDvSubjectSaveReqVO createReqVO); + + /** + * 更新点检保养项目 + * + * @param updateReqVO 更新信息 + */ + void updateSubject(@Valid MesDvSubjectSaveReqVO updateReqVO); + + /** + * 删除点检保养项目 + * + * @param id 编号 + */ + void deleteSubject(Long id); + + /** + * 获得点检保养项目 + * + * @param id 编号 + * @return 点检保养项目 + */ + MesDvSubjectDO getSubject(Long id); + + /** + * 获得点检保养项目分页 + * + * @param pageReqVO 分页查询 + * @return 点检保养项目分页 + */ + PageResult getSubjectPage(MesDvSubjectPageReqVO pageReqVO); + + /** + * 校验点检保养项目存在 + * + * @param id 编号 + */ + void validateSubjectExists(Long id); + + /** + * 获得点检保养项目列表 + * + * @return 项目列表 + */ + List getSubjectList(); + + /** + * 获得点检保养项目列表 + * + * @param ids 编号数组 + * @return 点检保养项目列表 + */ + List getSubjectList(Collection ids); + + /** + * 获得点检保养项目 Map + * + * @param ids 编号数组 + * @return 点检保养项目 Map + */ + default Map getSubjectMap(Collection ids) { + return convertMap(getSubjectList(ids), MesDvSubjectDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectServiceImpl.java new file mode 100644 index 000000000..d47fb075b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectServiceImpl.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.mes.service.dv.subject; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.dv.subject.MesDvSubjectDO; +import cn.iocoder.yudao.module.mes.dal.mysql.dv.subject.MesDvSubjectMapper; +import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanSubjectService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 点检保养项目 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesDvSubjectServiceImpl implements MesDvSubjectService { + + @Resource + private MesDvSubjectMapper subjectMapper; + // DONE @AI:调用对方的 service + @Resource + @Lazy + private MesDvCheckPlanSubjectService checkPlanSubjectService; + + @Override + public Long createSubject(MesDvSubjectSaveReqVO createReqVO) { + // 校验编码唯一 + validateSubjectCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesDvSubjectDO subject = BeanUtils.toBean(createReqVO, MesDvSubjectDO.class); + subjectMapper.insert(subject); + return subject.getId(); + } + + @Override + public void updateSubject(MesDvSubjectSaveReqVO updateReqVO) { + // 校验存在 + validateSubjectExists(updateReqVO.getId()); + // 校验编码唯一 + validateSubjectCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesDvSubjectDO updateObj = BeanUtils.toBean(updateReqVO, MesDvSubjectDO.class); + subjectMapper.updateById(updateObj); + } + + @Override + public void deleteSubject(Long id) { + // 校验存在 + validateSubjectExists(id); + // 校验是否被点检保养方案引用 + if (checkPlanSubjectService.getCheckPlanSubjectCountBySubjectId(id) > 0) { + throw exception(DV_SUBJECT_USED_BY_CHECK_PLAN); + } + + // 删除 + subjectMapper.deleteById(id); + } + + @Override + public void validateSubjectExists(Long id) { + if (subjectMapper.selectById(id) == null) { + throw exception(DV_SUBJECT_NOT_EXISTS); + } + } + + private void validateSubjectCodeUnique(Long id, String code) { + if (code == null) { + return; + } + MesDvSubjectDO subject = subjectMapper.selectByCode(code); + if (subject == null) { + return; + } + if (ObjUtil.notEqual(subject.getId(), id)) { + throw exception(DV_SUBJECT_CODE_DUPLICATE); + } + } + + @Override + public MesDvSubjectDO getSubject(Long id) { + return subjectMapper.selectById(id); + } + + @Override + public PageResult getSubjectPage(MesDvSubjectPageReqVO pageReqVO) { + return subjectMapper.selectPage(pageReqVO); + } + + @Override + public List getSubjectList() { + return subjectMapper.selectList(); + } + + @Override + public List getSubjectList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return subjectMapper.selectByIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/home/MesHomeStatisticsService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/home/MesHomeStatisticsService.java new file mode 100644 index 000000000..e96dc092a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/home/MesHomeStatisticsService.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.service.home; + +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeProductionTrendRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeSummaryRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeWorkOrderStatusRespVO; + +import java.util.List; + +/** + * MES 首页统计 Service 接口 + * + * @author 芋道源码 + */ +public interface MesHomeStatisticsService { + + /** + * 获得首页汇总统计 + * + * @return 汇总统计数据 + */ + MesHomeSummaryRespVO getHomeSummary(); + + /** + * 获得工单状态分布 + * + * @return 各状态的工单数量列表 + */ + List getWorkOrderStatusDistribution(); + + /** + * 获得生产趋势(近 N 天) + * + * @param days 天数 + * @return 每天的产量数据 + */ + List getProductionTrend(Integer days); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/home/MesHomeStatisticsServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/home/MesHomeStatisticsServiceImpl.java new file mode 100644 index 000000000..38bbc0369 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/home/MesHomeStatisticsServiceImpl.java @@ -0,0 +1,168 @@ +package cn.iocoder.yudao.module.mes.service.home; + +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeProductionTrendRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeSummaryRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.home.vo.MesHomeWorkOrderStatusRespVO; +import cn.iocoder.yudao.module.mes.dal.mysql.home.MesHomeStatisticsMapper; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvMachineryStatusEnum; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; + +/** + * MES 首页统计 Service 实现类 + * + * @author 芋道源码 + */ +@Service +public class MesHomeStatisticsServiceImpl implements MesHomeStatisticsService { + + @Resource + private MesHomeStatisticsMapper homeStatisticsMapper; + + @Override + public MesHomeSummaryRespVO getHomeSummary() { + MesHomeSummaryRespVO summary = new MesHomeSummaryRespVO(); + + // 1. 工单统计 + List> workOrderStats = homeStatisticsMapper.selectWorkOrderCountGroupByStatus(); + long activeCount = 0L; + long prepareCount = 0L; + long finishedCount = 0L; + for (Map stat : workOrderStats) { + int status = ((Number) stat.get("status")).intValue(); + long count = ((Number) stat.get("count")).longValue(); + if (status == MesProWorkOrderStatusEnum.CONFIRMED.getStatus()) { + activeCount = count; + } else if (status == MesProWorkOrderStatusEnum.PREPARE.getStatus()) { + prepareCount = count; + } else if (status == MesProWorkOrderStatusEnum.FINISHED.getStatus()) { + finishedCount = count; + } + } + summary.setWorkOrderActiveCount(activeCount); + summary.setWorkOrderPrepareCount(prepareCount); + summary.setWorkOrderFinishedCount(finishedCount); + + // 2. 今日产量 + LocalDateTime today = LocalDateTimeUtils.getToday(); + LocalDateTime yesterday = LocalDateTimeUtils.getYesterday(); + Map todayFeedback = homeStatisticsMapper.selectFeedbackSummary(today, null); + summary.setTodayOutput(getDecimal(todayFeedback, "feedbackQuantity")); + summary.setTodayQualifiedQuantity(getDecimal(todayFeedback, "qualifiedQuantity")); + summary.setTodayUnqualifiedQuantity(getDecimal(todayFeedback, "unqualifiedQuantity")); + + // 3. 昨日产量 + Map yesterdayFeedback = homeStatisticsMapper.selectFeedbackSummary(yesterday, today); + summary.setYesterdayOutput(getDecimal(yesterdayFeedback, "feedbackQuantity")); + + // 4. 设备统计 + List> machineryStats = homeStatisticsMapper.selectMachineryCountGroupByStatus(); + long total = 0L; + long producing = 0L; + long stop = 0L; + long maintenance = 0L; + for (Map stat : machineryStats) { + int status = ((Number) stat.get("status")).intValue(); + long count = ((Number) stat.get("count")).longValue(); + total += count; + if (status == MesDvMachineryStatusEnum.PRODUCING.getStatus()) { + producing = count; + } else if (status == MesDvMachineryStatusEnum.STOP.getStatus()) { + stop = count; + } else if (status == MesDvMachineryStatusEnum.MAINTENANCE.getStatus()) { + maintenance = count; + } + } + summary.setMachineryTotal(total); + summary.setMachineryProducing(producing); + summary.setMachineryStop(stop); + summary.setMachineryMaintenance(maintenance); + + // 5. 异常/待办 + summary.setAndonActiveCount(homeStatisticsMapper.selectAndonActiveCount()); + summary.setRepairActiveCount(homeStatisticsMapper.selectRepairActiveCount()); + + return summary; + } + + @Override + public List getWorkOrderStatusDistribution() { + List> stats = homeStatisticsMapper.selectWorkOrderCountGroupByStatus(); + List result = new ArrayList<>(); + for (MesProWorkOrderStatusEnum statusEnum : MesProWorkOrderStatusEnum.values()) { + long count = 0L; + for (Map stat : stats) { + if (((Number) stat.get("status")).intValue() == statusEnum.getStatus()) { + count = ((Number) stat.get("count")).longValue(); + break; + } + } + result.add(new MesHomeWorkOrderStatusRespVO(statusEnum.getStatus(), statusEnum.getName(), count)); + } + return result; + } + + @Override + public List getProductionTrend(Integer days) { + LocalDate endDate = LocalDate.now().plusDays(1); + LocalDate startDate = endDate.minusDays(days); + LocalDateTime beginTime = startDate.atStartOfDay(); + LocalDateTime endTime = endDate.atStartOfDay(); + + // 查询数据库 + List> dbData = homeStatisticsMapper.selectDailyFeedbackTrend(beginTime, endTime); + Map> dateMap = new LinkedHashMap<>(); + for (Map row : dbData) { + dateMap.put((String) row.get("date"), row); + } + + // 补全所有日期(无数据的日期填 0) + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + List result = new ArrayList<>(); + for (LocalDate d = startDate; d.isBefore(endDate); d = d.plusDays(1)) { + String dateStr = d.format(fmt); + Map row = dateMap.get(dateStr); + MesHomeProductionTrendRespVO vo = new MesHomeProductionTrendRespVO(); + vo.setDate(dateStr); + if (row != null) { + vo.setQuantity(getDecimalFromObj(row.get("quantity"))); + vo.setQualifiedQuantity(getDecimalFromObj(row.get("qualifiedQuantity"))); + vo.setUnqualifiedQuantity(getDecimalFromObj(row.get("unqualifiedQuantity"))); + } else { + vo.setQuantity(BigDecimal.ZERO); + vo.setQualifiedQuantity(BigDecimal.ZERO); + vo.setUnqualifiedQuantity(BigDecimal.ZERO); + } + result.add(vo); + } + return result; + } + + // ========== 工具方法 ========== + + private BigDecimal getDecimal(Map map, String key) { + if (map == null || map.get(key) == null) { + return BigDecimal.ZERO; + } + return map.get(key); + } + + private BigDecimal getDecimalFromObj(Object obj) { + if (obj == null) { + return BigDecimal.ZERO; + } + if (obj instanceof BigDecimal) { + return (BigDecimal) obj; + } + return new BigDecimal(obj.toString()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartService.java new file mode 100644 index 000000000..ea782ed52 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 编码规则组成 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdAutoCodePartService { + + /** + * 创建规则组成 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createAutoCodePart(@Valid MesMdAutoCodePartSaveReqVO createReqVO); + + /** + * 更新规则组成 + * + * @param updateReqVO 更新信息 + */ + void updateAutoCodePart(@Valid MesMdAutoCodePartSaveReqVO updateReqVO); + + /** + * 删除规则组成 + * + * @param id 编号 + */ + void deleteAutoCodePart(Long id); + + /** + * 获得规则组成 + * + * @param id 编号 + * @return 规则组成 + */ + MesMdAutoCodePartDO getAutoCodePart(Long id); + + /** + * 获得规则组成列表(根据规则 ID) + * + * @param ruleId 规则 ID + * @return 规则组成列表 + */ + List getAutoCodePartListByRuleId(Long ruleId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartServiceImpl.java new file mode 100644 index 000000000..fb9e4595f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartServiceImpl.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodePartMapper; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.AUTO_CODE_PART_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.AUTO_CODE_PART_SERIAL_NUMBER_DUPLICATE; + +/** + * MES 编码规则组成 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdAutoCodePartServiceImpl implements MesMdAutoCodePartService { + + @Resource + private MesMdAutoCodePartMapper partMapper; + + @Resource + private MesMdAutoCodeRuleService ruleService; + + @Override + public Long createAutoCodePart(MesMdAutoCodePartSaveReqVO createReqVO) { + // 校验规则存在 + ruleService.validateAutoCodeRuleExists(createReqVO.getRuleId()); + // 校验流水号分段唯一性 + validateSerialNumberPartUnique(null, createReqVO.getRuleId(), createReqVO.getType()); + + // 插入 + MesMdAutoCodePartDO part = BeanUtils.toBean(createReqVO, MesMdAutoCodePartDO.class); + partMapper.insert(part); + return part.getId(); + } + + @Override + public void updateAutoCodePart(MesMdAutoCodePartSaveReqVO updateReqVO) { + // 校验存在 + validatePartExists(updateReqVO.getId()); + // 校验规则存在 + ruleService.validateAutoCodeRuleExists(updateReqVO.getRuleId()); + // 校验流水号分段唯一性 + validateSerialNumberPartUnique(updateReqVO.getId(), updateReqVO.getRuleId(), updateReqVO.getType()); + + // 更新 + MesMdAutoCodePartDO updateObj = BeanUtils.toBean(updateReqVO, MesMdAutoCodePartDO.class); + partMapper.updateById(updateObj); + } + + @Override + public void deleteAutoCodePart(Long id) { + // 校验存在 + validatePartExists(id); + + // 删除 + partMapper.deleteById(id); + } + + @Override + public MesMdAutoCodePartDO getAutoCodePart(Long id) { + return partMapper.selectById(id); + } + + @Override + public List getAutoCodePartListByRuleId(Long ruleId) { + return partMapper.selectListByRuleId(ruleId); + } + + // ==================== 校验方法 ==================== + + private void validatePartExists(Long id) { + if (partMapper.selectById(id) == null) { + throw exception(AUTO_CODE_PART_NOT_EXISTS); + } + } + + private void validateSerialNumberPartUnique(Long id, Long ruleId, Integer type) { + // 只有流水号类型才需要校验 + if (ObjUtil.notEqual(MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType(), type)) { + return; + } + // 查询该规则下所有流水号分段 + List parts = partMapper.selectListByRuleId(ruleId); + long count = parts.stream() + .filter(part -> MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType().equals(part.getType())) + .filter(part -> ObjUtil.notEqual(id, part.getId())) // 排除自己 + .count(); + if (count > 0) { + throw exception(AUTO_CODE_PART_SERIAL_NUMBER_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordService.java new file mode 100644 index 000000000..13edef453 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordService.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +/** + * MES 编码生成记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdAutoCodeRecordService { + + /** + * 生成编码(无输入字符) + * + * @param ruleCode 规则编码 + * @return 生成的编码 + */ + default String generateAutoCode(String ruleCode) { + return generateAutoCode(ruleCode, null); + } + + /** + * 生成编码 + * + * @param ruleCode 规则编码 + * @param inputChar 输入字符 + * @return 生成的编码 + */ + String generateAutoCode(String ruleCode, String inputChar); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java new file mode 100644 index 000000000..25cf9ae92 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodeRecordMapper; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePaddedMethodEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 编码生成记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdAutoCodeRecordServiceImpl implements MesMdAutoCodeRecordService { + + @Resource + private MesMdAutoCodeRecordMapper recordMapper; + + @Resource + private MesMdAutoCodeRuleService ruleService; + @Resource + private MesMdAutoCodePartService partService; + + @Resource + private List strategyList; + private Map strategyMap; + + @PostConstruct + public void init() { + strategyMap = CollectionUtils.convertMap(strategyList, MesMdAutoCodePartStrategy::getType); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String generateAutoCode(String ruleCode, String inputChar) { + // 1.1 查询规则 + MesMdAutoCodeRuleDO rule = ruleService.getAutoCodeRuleByCode(ruleCode); + if (rule == null) { + throw exception(AUTO_CODE_RULE_NOT_EXISTS); + } + // 1.2 查询规则组成 + List parts = partService.getAutoCodePartListByRuleId(rule.getId()); + if (CollUtil.isEmpty(parts)) { + throw exception(AUTO_CODE_GENERATE_FAILED); + } + + // 2.1 构建上下文 + MesMdAutoCodeContext context = new MesMdAutoCodeContext() + .setRule(rule).setParts(parts).setInputChar(inputChar); + // 2.2 遍历分段,生成编码 + StringBuilder codeBuilder = new StringBuilder(); + for (MesMdAutoCodePartDO part : parts) { + MesMdAutoCodePartStrategy strategy = strategyMap.get(part.getType()); + Assert.notNull(strategy, () -> exception(AUTO_CODE_GENERATE_FAILED)); + // 生成分段编码 + String partCode = strategy.generate(part, context); + // 统一截取指定长度 + partCode = StrUtil.sub(partCode, 0, part.getLength()); + // 拼接分段编码 + codeBuilder.append(partCode); + } + // 2.3 补齐处理 + String result = codeBuilder.toString(); + if (Boolean.TRUE.equals(rule.getPadded()) && rule.getMaxLength() != null) { + result = padCode(result, rule); + } + + // 3.1 二次校验(防止重复) + MesMdAutoCodeRecordDO existRecord = recordMapper.selectByResult(result); + if (existRecord != null) { + throw exception(AUTO_CODE_GENERATE_FAILED); + } + // 3.2 保存生成记录 + MesMdAutoCodeRecordDO record = new MesMdAutoCodeRecordDO() + .setRuleId(rule.getId()).setResult(result) + .setSerialNo(context.getSerialNo()).setInputChar(inputChar); + recordMapper.insert(record); + return result; + } + + /** + * 补齐编码 + */ + private String padCode(String code, MesMdAutoCodeRuleDO rule) { + if (code.length() >= rule.getMaxLength()) { + return StrUtil.sub(code, 0, rule.getMaxLength()); + } + String paddedChar = StrUtil.emptyToDefault(rule.getPaddedChar(), "0"); + Integer paddedMethod = rule.getPaddedMethod() != null ? rule.getPaddedMethod() : MesMdAutoCodePaddedMethodEnum.LEFT.getMethod(); + if (MesMdAutoCodePaddedMethodEnum.LEFT.getMethod().equals(paddedMethod)) { + // 左补齐 + return StrUtil.padPre(code, rule.getMaxLength(), paddedChar.charAt(0)); + } else { + // 右补齐 + return StrUtil.padAfter(code, rule.getMaxLength(), paddedChar.charAt(0)); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleService.java new file mode 100644 index 000000000..c4aebf60d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleService.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRulePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 编码规则 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdAutoCodeRuleService { + + /** + * 创建编码规则 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createAutoCodeRule(@Valid MesMdAutoCodeRuleSaveReqVO createReqVO); + + /** + * 更新编码规则 + * + * @param updateReqVO 更新信息 + */ + void updateAutoCodeRule(@Valid MesMdAutoCodeRuleSaveReqVO updateReqVO); + + /** + * 删除编码规则 + * + * @param id 编号 + */ + void deleteAutoCodeRule(Long id); + + /** + * 获得编码规则 + * + * @param id 编号 + * @return 编码规则 + */ + MesMdAutoCodeRuleDO getAutoCodeRule(Long id); + + /** + * 获得编码规则分页 + * + * @param pageReqVO 分页查询 + * @return 编码规则分页 + */ + PageResult getAutoCodeRulePage(MesMdAutoCodeRulePageReqVO pageReqVO); + + /** + * 获得编码规则列表(根据状态) + * + * @param status 状态 + * @return 编码规则列表 + */ + List getAutoCodeRuleListByStatus(Integer status); + + /** + * 根据规则编码获取规则 + * + * @param code 规则编码 + * @return 编码规则 + */ + MesMdAutoCodeRuleDO getAutoCodeRuleByCode(String code); + + /** + * 校验编码规则是否存在 + * + * @param id 编号 + */ + void validateAutoCodeRuleExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleServiceImpl.java new file mode 100644 index 000000000..fda34fcbd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleServiceImpl.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRulePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodePartMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodeRuleMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 编码规则 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdAutoCodeRuleServiceImpl implements MesMdAutoCodeRuleService { + + @Resource + private MesMdAutoCodeRuleMapper ruleMapper; + + @Resource + private MesMdAutoCodePartMapper partMapper; + + @Override + public Long createAutoCodeRule(MesMdAutoCodeRuleSaveReqVO createReqVO) { + // 校验规则编码的唯一性 + validateRuleCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesMdAutoCodeRuleDO rule = BeanUtils.toBean(createReqVO, MesMdAutoCodeRuleDO.class); + ruleMapper.insert(rule); + return rule.getId(); + } + + @Override + public void updateAutoCodeRule(MesMdAutoCodeRuleSaveReqVO updateReqVO) { + // 校验存在 + validateAutoCodeRuleExists(updateReqVO.getId()); + // 校验规则编码的唯一性 + validateRuleCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesMdAutoCodeRuleDO updateObj = BeanUtils.toBean(updateReqVO, MesMdAutoCodeRuleDO.class); + ruleMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteAutoCodeRule(Long id) { + // 校验存在 + validateAutoCodeRuleExists(id); + + // 删除规则 + ruleMapper.deleteById(id); + // 级联删除规则组成 + partMapper.deleteByRuleId(id); + } + + @Override + public MesMdAutoCodeRuleDO getAutoCodeRule(Long id) { + return ruleMapper.selectById(id); + } + + @Override + public PageResult getAutoCodeRulePage(MesMdAutoCodeRulePageReqVO pageReqVO) { + return ruleMapper.selectPage(pageReqVO); + } + + @Override + public List getAutoCodeRuleListByStatus(Integer status) { + return ruleMapper.selectListByStatus(status); + } + + @Override + public MesMdAutoCodeRuleDO getAutoCodeRuleByCode(String code) { + return ruleMapper.selectByCode(code); + } + + @Override + public void validateAutoCodeRuleExists(Long id) { + if (ruleMapper.selectById(id) == null) { + throw exception(AUTO_CODE_RULE_NOT_EXISTS); + } + } + + // ==================== 校验方法 ==================== + + private void validateRuleCodeUnique(Long id, String code) { + MesMdAutoCodeRuleDO rule = ruleMapper.selectByCode(code); + if (rule == null) { + return; + } + if (ObjUtil.notEqual(id, rule.getId())) { + throw exception(AUTO_CODE_RULE_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodeContext.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodeContext.java new file mode 100644 index 000000000..bb1a13ba6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodeContext.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy; + +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import lombok.Data; + +import java.util.List; + +/** + * MES 编码生成上下文 + * + * @author 芋道源码 + */ +@Data +public class MesMdAutoCodeContext { + + /** + * 规则 + */ + private MesMdAutoCodeRuleDO rule; + /** + * 规则组成列表 + */ + private List parts; + + /** + * 输入字符 + */ + private String inputChar; + + /** + * 流水号 + * + * 由流水号策略生成并设置,用于保存到生成记录表。例如:当规则包含流水号分段时,生成编码 "ITEM_20260304_0001",此字段值为 1 + */ + private Long serialNo; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodePartStrategy.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodePartStrategy.java new file mode 100644 index 000000000..1d7372acb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodePartStrategy.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy; + +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; + +/** + * MES 编码规则分段策略接口 + * + * @author 芋道源码 + */ +public interface MesMdAutoCodePartStrategy { + + /** + * 获取策略类型 + * + * @return 分段类型 + */ + Integer getType(); + + /** + * 生成分段内容 + * + * @param part 规则组成 + * @param context 上下文 + * @return 分段内容 + */ + String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategy.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategy.java new file mode 100644 index 000000000..cabfa1924 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategy.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * MES 编码规则 - 当前日期策略 + * + * @author 芋道源码 + */ +@Component +public class MesMdAutoCodeDatePartStrategy implements MesMdAutoCodePartStrategy { + + @Override + public Integer getType() { + return MesMdAutoCodePartTypeEnum.DATE.getType(); + } + + @Override + public String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + String dateFormat = StrUtil.emptyToDefault(part.getDateFormat(), DatePattern.PURE_DATE_PATTERN); + return DateUtil.format(LocalDateTime.now(), dateFormat); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategy.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategy.java new file mode 100644 index 000000000..55ece91a3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategy.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import org.springframework.stereotype.Component; + +/** + * MES 编码规则 - 固定字符策略 + * + * @author 芋道源码 + */ +@Component +public class MesMdAutoCodeFixedCharPartStrategy implements MesMdAutoCodePartStrategy { + + @Override + public Integer getType() { + return MesMdAutoCodePartTypeEnum.FIXED_CHAR.getType(); + } + + @Override + public String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + return StrUtil.emptyToDefault(part.getFixCharacter(), ""); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategy.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategy.java new file mode 100644 index 000000000..f3c556105 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategy.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import org.springframework.stereotype.Component; + +/** + * MES 编码规则 - 输入字符策略 + * + * @author 芋道源码 + */ +@Component +public class MesMdAutoCodeInputCharPartStrategy implements MesMdAutoCodePartStrategy { + + @Override + public Integer getType() { + return MesMdAutoCodePartTypeEnum.INPUT_CHAR.getType(); + } + + @Override + public String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + String inputChar = context.getInputChar(); + return StrUtil.emptyToDefault(inputChar, ""); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategy.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategy.java new file mode 100644 index 000000000..3a5c05590 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategy.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.redis.md.autocode.MesMdAutoCodeRedisDAO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeCycleMethodEnum; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.time.LocalDateTime; + +/** + * MES 编码规则 - 流水号策略 + * + * @author 芋道源码 + */ +@Component +public class MesMdAutoCodeSerialNumberPartStrategy implements MesMdAutoCodePartStrategy { + + @Resource + private MesMdAutoCodeRedisDAO redisDAO; + + @Override + public Integer getType() { + return MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType(); + } + + @Override + public String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + // 1.1 构建 Redis key 后缀 + String keySuffix = buildRedisKeySuffix(part, context); + // 1.2 获取过期时间 + Duration duration = Boolean.TRUE.equals(part.getCycleFlag()) ? getExpireDuration(part.getCycleMethod()) : null; + + // 2. 获取流水号 + Integer step = part.getSerialStep() != null ? part.getSerialStep() : 1; + Integer startNo = part.getSerialStartNo() != null ? part.getSerialStartNo() : 1; + Long serialNo = redisDAO.increment(keySuffix, duration, startNo, step); + + // 3. 格式化输出(补零) + String serialStr = String.valueOf(serialNo); + if (serialStr.length() < part.getLength()) { + serialStr = StrUtil.padPre(serialStr, part.getLength(), '0'); + } + context.setSerialNo(serialNo); + return serialStr; + } + + /** + * 构建 Redis key 后缀 + */ + private String buildRedisKeySuffix(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + StringBuilder keySuffix = new StringBuilder(); + keySuffix.append(context.getRule().getId()); + + // 如果不循环,直接返回 + if (!Boolean.TRUE.equals(part.getCycleFlag()) || part.getCycleMethod() == null) { + return keySuffix.toString(); + } + + // 根据循环方式构建 key 后缀 + keySuffix.append(":"); + LocalDateTime time = LocalDateTime.now(); + if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.YEAR.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyy")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.MONTH.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyyMM")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.DAY.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyyMMdd")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.HOUR.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyyMMddHH")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.MINUTE.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyyMMddHHmm")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.INPUT_CHAR.getMethod())) { + if (StrUtil.isNotEmpty(context.getInputChar())) { + keySuffix.append(context.getInputChar()); + } + } else { + throw new IllegalArgumentException("未知的循环方式:" + part.getCycleMethod()); + } + return keySuffix.toString(); + } + + /** + * 获取过期时间 + */ + private Duration getExpireDuration(Integer cycleMethod) { + if (cycleMethod == null) { + return Duration.ofDays(1); + } + if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.YEAR.getMethod())) { + return Duration.ofDays(366); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.MONTH.getMethod())) { + return Duration.ofDays(32); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.DAY.getMethod())) { + return Duration.ofDays(2); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.HOUR.getMethod())) { + return Duration.ofHours(2); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.MINUTE.getMethod())) { + return Duration.ofMinutes(2); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.INPUT_CHAR.getMethod())) { + // 永不过期 + return null; + } else { + throw new IllegalArgumentException("未知的循环方式:" + cycleMethod); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java new file mode 100644 index 000000000..7c86f42da --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.mes.service.md.client; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 客户 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdClientService { + + /** + * 创建客户 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createClient(@Valid MesMdClientSaveReqVO createReqVO); + + /** + * 更新客户 + * + * @param updateReqVO 更新信息 + */ + void updateClient(@Valid MesMdClientSaveReqVO updateReqVO); + + /** + * 删除客户 + * + * @param id 编号 + */ + void deleteClient(Long id); + + /** + * 获得客户 + * + * @param id 编号 + * @return 客户 + */ + MesMdClientDO getClient(Long id); + + /** + * 获得客户分页 + * + * @param pageReqVO 分页查询 + * @return 客户分页 + */ + PageResult getClientPage(MesMdClientPageReqVO pageReqVO); + + /** + * 获得客户列表 + * + * @param ids 编号列表 + * @return 客户列表 + */ + List getClientList(Collection ids); + + /** + * 获得客户 Map + * + * @param ids 编号列表 + * @return 客户 Map + */ + default Map getClientMap(Collection ids) { + return convertMap(getClientList(ids), MesMdClientDO::getId); + } + + /** + * 校验客户是否存在 + * + * @param id 编号 + */ + void validateClientExists(Long id); + + /** + * 批量导入客户 + * + * @param importClients 导入客户列表 + * @param updateSupport 是否支持更新 + * @return 导入结果 + */ + MesMdClientImportRespVO importClientList(List importClients, boolean updateSupport); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java new file mode 100644 index 000000000..03b53b971 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java @@ -0,0 +1,217 @@ +package cn.iocoder.yudao.module.mes.service.md.client; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.client.MesMdClientMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 客户 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdClientServiceImpl implements MesMdClientService { + + @Resource + private MesMdClientMapper clientMapper; + + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createClient(MesMdClientSaveReqVO createReqVO) { + // 校验数据 + validateClientSaveData(createReqVO); + + // 插入 + MesMdClientDO client = BeanUtils.toBean(createReqVO, MesMdClientDO.class); + clientMapper.insert(client); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.CLIENT.getValue(), + client.getId(), client.getCode(), client.getName()); + return client.getId(); + } + + @Override + public void updateClient(MesMdClientSaveReqVO updateReqVO) { + // 校验存在 + validateClientExists(updateReqVO.getId()); + // 校验数据 + validateClientSaveData(updateReqVO); + + // 更新 + MesMdClientDO updateObj = BeanUtils.toBean(updateReqVO, MesMdClientDO.class); + clientMapper.updateById(updateObj); + } + + private void validateClientSaveData(MesMdClientSaveReqVO reqVO) { + // 校验编码唯一 + validateClientCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验名称唯一 + validateClientNameUnique(reqVO.getId(), reqVO.getName()); + // 校验简称唯一 + validateClientNicknameUnique(reqVO.getId(), reqVO.getNickname()); + } + + @Override + public void deleteClient(Long id) { + // 校验存在 + validateClientExists(id); + // 删除 + clientMapper.deleteById(id); + } + + @Override + public void validateClientExists(Long id) { + if (clientMapper.selectById(id) == null) { + throw exception(MD_CLIENT_NOT_EXISTS); + } + } + + private void validateClientCodeUnique(Long id, String code) { + MesMdClientDO client = clientMapper.selectByCode(code); + if (client == null) { + return; + } + if (ObjUtil.notEqual(client.getId(), id)) { + throw exception(MD_CLIENT_CODE_DUPLICATE); + } + } + + private void validateClientNameUnique(Long id, String name) { + MesMdClientDO client = clientMapper.selectByName(name); + if (client == null) { + return; + } + if (ObjUtil.notEqual(client.getId(), id)) { + throw exception(MD_CLIENT_NAME_DUPLICATE); + } + } + + private void validateClientNicknameUnique(Long id, String nickname) { + if (StrUtil.isEmpty(nickname)) { + return; + } + MesMdClientDO client = clientMapper.selectByNickname(nickname); + if (client == null) { + return; + } + if (ObjUtil.notEqual(client.getId(), id)) { + throw exception(MD_CLIENT_NICKNAME_DUPLICATE); + } + } + + @Override + public MesMdClientDO getClient(Long id) { + return clientMapper.selectById(id); + } + + @Override + public PageResult getClientPage(MesMdClientPageReqVO pageReqVO) { + return clientMapper.selectPage(pageReqVO); + } + + @Override + public List getClientList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return clientMapper.selectByIds(ids); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MesMdClientImportRespVO importClientList(List importClients, boolean updateSupport) { + // 1. 参数校验 + if (CollUtil.isEmpty(importClients)) { + throw exception(MD_CLIENT_IMPORT_LIST_IS_EMPTY); + } + + // 2. 遍历,逐个创建 or 更新 + MesMdClientImportRespVO respVO = MesMdClientImportRespVO.builder() + .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>()) + .failureCodes(new LinkedHashMap<>()).build(); + AtomicInteger index = new AtomicInteger(1); + importClients.forEach(importClient -> { + int currentIndex = index.getAndIncrement(); + // 2.1 校验字段 + String key = StrUtil.blankToDefault(importClient.getCode(), "第 " + currentIndex + " 行"); + if (StrUtil.isBlank(importClient.getCode())) { + respVO.getFailureCodes().put(key, "客户编码不能为空"); + return; + } + if (StrUtil.isBlank(importClient.getName())) { + respVO.getFailureCodes().put(key, "客户名称不能为空"); + return; + } + if (importClient.getType() == null) { + respVO.getFailureCodes().put(key, "客户类型不能为空"); + return; + } + + // 2.2 判断:创建 or 更新 + MesMdClientDO existClient = clientMapper.selectByCode(importClient.getCode()); + if (existClient == null) { + // 2.2.1 创建 + try { + validateClientNameUnique(null, importClient.getName()); + validateClientNicknameUnique(null, importClient.getNickname()); + } catch (ServiceException ex) { + respVO.getFailureCodes().put(key, ex.getMessage()); + return; + } + MesMdClientDO client = BeanUtils.toBean(importClient, MesMdClientDO.class); + clientMapper.insert(client); + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.CLIENT.getValue(), + client.getId(), client.getCode(), client.getName()); + respVO.getCreateCodes().add(importClient.getCode()); + } else if (updateSupport) { + // 2.2.2 更新 + try { + validateClientNameUnique(existClient.getId(), importClient.getName()); + validateClientNicknameUnique(existClient.getId(), importClient.getNickname()); + } catch (ServiceException ex) { + respVO.getFailureCodes().put(key, ex.getMessage()); + return; + } + MesMdClientDO updateObj = BeanUtils.toBean(importClient, MesMdClientDO.class); + updateObj.setId(existClient.getId()); + clientMapper.updateById(updateObj); + respVO.getUpdateCodes().add(importClient.getCode()); + } else { + // 不支持更新 + respVO.getFailureCodes().put(key, "客户编码已存在"); + } + }); + return respVO; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemBatchConfigService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemBatchConfigService.java new file mode 100644 index 000000000..39651f04f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemBatchConfigService.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.batchconfig.MesMdItemBatchConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO; +import jakarta.validation.Valid; + +/** + * MES 物料批次属性配置 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdItemBatchConfigService { + + /** + * 根据物料编号获取批次属性配置 + * + * @param itemId 物料编号 + * @return 批次属性配置,不存在则返回 null + */ + MesMdItemBatchConfigDO getItemBatchConfigByItemId(Long itemId); + + /** + * 校验物料批次配置存在 + * + * @param itemId 物料 ID + * @return 物料批次配置 + */ + MesMdItemBatchConfigDO validateItemBatchConfigExists(Long itemId); + + /** + * 保存批次属性配置(新增或更新) + * + * @param saveReqVO 保存信息 + * @return 配置编号 + */ + Long saveItemBatchConfig(@Valid MesMdItemBatchConfigSaveReqVO saveReqVO); + + /** + * 根据物料编号删除批次属性配置 + * + * @param itemId 物料编号 + */ + void deleteItemBatchConfigByItemId(Long itemId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemBatchConfigServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemBatchConfigServiceImpl.java new file mode 100644 index 000000000..84010c660 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemBatchConfigServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.batchconfig.MesMdItemBatchConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemBatchConfigMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_BATCH_CONFIG_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_NOT_EXISTS; + +/** + * MES 物料批次属性配置 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdItemBatchConfigServiceImpl implements MesMdItemBatchConfigService { + + @Resource + private MesMdItemBatchConfigMapper itemBatchConfigMapper; + + @Resource + @Lazy // 避免循环依赖(MesMdItemServiceImpl 也会注入本 Service) + private MesMdItemService itemService; + + @Override + public MesMdItemBatchConfigDO getItemBatchConfigByItemId(Long itemId) { + return itemBatchConfigMapper.selectByItemId(itemId); + } + + @Override + public MesMdItemBatchConfigDO validateItemBatchConfigExists(Long itemId) { + MesMdItemBatchConfigDO config = getItemBatchConfigByItemId(itemId); + if (config == null) { + throw exception(MD_ITEM_BATCH_CONFIG_NOT_EXISTS); + } + return config; + } + + @Override + public Long saveItemBatchConfig(MesMdItemBatchConfigSaveReqVO saveReqVO) { + // 1. 校验物料存在 + if (itemService.getItem(saveReqVO.getItemId()) == null) { + throw exception(MD_ITEM_NOT_EXISTS); + } + + // 2. 查询已有配置,决定新增还是更新 + MesMdItemBatchConfigDO existing = itemBatchConfigMapper.selectByItemId(saveReqVO.getItemId()); + if (existing != null) { + // 更新 + MesMdItemBatchConfigDO updateObj = BeanUtils.toBean(saveReqVO, MesMdItemBatchConfigDO.class); + updateObj.setId(existing.getId()); + itemBatchConfigMapper.updateById(updateObj); + return existing.getId(); + } + + // 新增 + MesMdItemBatchConfigDO insertObj = BeanUtils.toBean(saveReqVO, MesMdItemBatchConfigDO.class); + itemBatchConfigMapper.insert(insertObj); + return insertObj.getId(); + } + + @Override + public void deleteItemBatchConfigByItemId(Long itemId) { + itemBatchConfigMapper.deleteByItemId(itemId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java new file mode 100644 index 000000000..d35cc4bc6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 物料产品 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdItemService { + + /** + * 创建物料产品 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createItem(@Valid MesMdItemSaveReqVO createReqVO); + + /** + * 更新物料产品 + * + * @param updateReqVO 更新信息 + */ + void updateItem(@Valid MesMdItemSaveReqVO updateReqVO); + + /** + * 更新物料产品状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateItemStatus(Long id, Integer status); + + /** + * 删除物料产品 + * + * @param id 编号 + */ + void deleteItem(Long id); + + /** + * 获得物料产品 + * + * @param id 编号 + * @return 物料产品 + */ + MesMdItemDO getItem(Long id); + + /** + * 校验物料产品存在 + * + * @param id 编号 + * @return 物料产品 + */ + MesMdItemDO validateItemExists(Long id); + + /** + * 获得物料产品分页 + * + * @param pageReqVO 分页查询 + * @return 物料产品分页 + */ + PageResult getItemPage(MesMdItemPageReqVO pageReqVO); + + /** + * 获得物料产品列表 + * + * @param ids 编号数组 + * @return 物料产品列表 + */ + List getItemList(Collection ids); + + /** + * 获得物料产品 Map + * + * @param ids 编号数组 + * @return 物料产品 Map + */ + default Map getItemMap(Collection ids) { + return convertMap(getItemList(ids), MesMdItemDO::getId); + } + + /** + * 基于物料分类编号,获得物料数量 + * + * @param itemTypeId 物料分类编号 + * @return 物料数量 + */ + Long getItemCountByItemTypeId(Long itemTypeId); + + /** + * 批量导入物料 + * + * @param importItems 导入物料列表 + * @param updateSupport 是否支持更新 + * @return 导入结果 + */ + MesMdItemImportRespVO importItemList(List importItems, boolean updateSupport); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java new file mode 100644 index 000000000..47af46b49 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java @@ -0,0 +1,342 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemSaveReqVO; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemMapper; +import cn.iocoder.yudao.module.mes.enums.md.MesMdItemTypeEnum; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 物料产品 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdItemServiceImpl implements MesMdItemService { + + @Resource + private MesMdItemMapper itemMapper; + + @Resource + private MesMdItemTypeService itemTypeService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesMdItemBatchConfigService itemBatchConfigService; + @Resource + private MesMdProductBomService productBomService; + @Resource + private MesMdProductSopService productSopService; + @Resource + private MesMdProductSipService productSipService; + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createItem(MesMdItemSaveReqVO createReqVO) { + // 校验数据 + validateItemSaveData(createReqVO); + + // 插入 + MesMdItemDO item = BeanUtils.toBean(createReqVO, MesMdItemDO.class); + item.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 默认禁用。信息完成后,再启用 + clearStockIfNotSafe(item); // 如果未启用安全库存,清零库存上下限 + itemMapper.insert(item); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.ITEM.getValue(), + item.getId(), item.getCode(), item.getName()); + return item.getId(); + } + + @Override + public void updateItem(MesMdItemSaveReqVO updateReqVO) { + // 校验存在 + validateItemExists(updateReqVO.getId()); + // 校验数据 + validateItemSaveData(updateReqVO); + + // 更新 + MesMdItemDO updateObj = BeanUtils.toBean(updateReqVO, MesMdItemDO.class); + clearStockIfNotSafe(updateObj); // 如果未启用安全库存,清零库存上下限 + itemMapper.updateById(updateObj); + } + + private void validateItemSaveData(MesMdItemSaveReqVO reqVO) { + // 校验物料编码的唯一性 + validateItemCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验物料名称的唯一性 + validateItemNameUnique(reqVO.getId(), reqVO.getName()); + // 校验物料分类存在 + validateItemTypeExists(reqVO.getItemTypeId()); + // 校验计量单位存在 + validateUnitMeasureExists(reqVO.getUnitMeasureId()); + } + + @Override + public void updateItemStatus(Long id, Integer status) { + // 校验存在 + MesMdItemDO item = validateItemExists(id); + if (CommonStatusEnum.isEnable(status)) { + // 如果启用了批次管理,校验批次属性配置 + if (Boolean.TRUE.equals(item.getBatchFlag())) { + validateBatchConfigExists(id); + } + // 如果是产品类型,校验必须配置 BOM + MesMdItemTypeDO itemType = itemTypeService.getItemType(item.getItemTypeId()); + if (MesMdItemTypeEnum.isProduct(itemType.getItemOrProduct())) { + if (CollUtil.isEmpty(productBomService.getProductBomListByItemId(id))) { + throw exception(MD_ITEM_PRODUCT_BOM_REQUIRED); + } + } + } + + // 更新状态 + itemMapper.updateById(new MesMdItemDO().setId(id).setStatus(status)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteItem(Long id) { + // 校验存在 + validateItemExists(id); + + // 级联删除批次属性配置 + itemBatchConfigService.deleteItemBatchConfigByItemId(id); + // 级联删除产品BOM + productBomService.deleteProductBomByItemId(id); + // 级联删除产品SOP + productSopService.deleteProductSopByItemId(id); + // 级联删除产品SIP + productSipService.deleteProductSipByItemId(id); + // 删除 + itemMapper.deleteById(id); + } + + @Override + public MesMdItemDO validateItemExists(Long id) { + MesMdItemDO item = itemMapper.selectById(id); + if (item == null) { + throw exception(MD_ITEM_NOT_EXISTS); + } + return item; + } + + private void validateItemCodeUnique(Long id, String code) { + MesMdItemDO item = itemMapper.selectByCode(code); + if (item == null) { + return; + } + if (ObjUtil.notEqual(item.getId(), id)) { + throw exception(MD_ITEM_CODE_DUPLICATE); + } + } + + private void validateItemNameUnique(Long id, String name) { + MesMdItemDO item = itemMapper.selectByName(name); + if (item == null) { + return; + } + if (ObjUtil.notEqual(item.getId(), id)) { + throw exception(MD_ITEM_NAME_DUPLICATE); + } + } + + private void validateItemTypeExists(Long itemTypeId) { + if (itemTypeService.getItemType(itemTypeId) == null) { + throw exception(MD_ITEM_TYPE_NOT_EXISTS); + } + } + + private void validateUnitMeasureExists(Long unitMeasureId) { + if (unitMeasureService.getUnitMeasure(unitMeasureId) == null) { + throw exception(MD_UNIT_MEASURE_NOT_EXISTS); + } + } + + /** + * 如果未启用安全库存,清零库存上下限 + */ + private void clearStockIfNotSafe(MesMdItemDO item) { + if (Boolean.TRUE.equals(item.getSafeStockFlag())) { + return; + } + item.setMinStock(BigDecimal.ZERO).setMaxStock(BigDecimal.ZERO); + } + + /** + * 如果启用了批次管理且状态为开启,校验批次属性配置是否存在且至少一个属性为 true + */ + private void validateBatchConfigExists(Long itemId) { + MesMdItemBatchConfigDO config = itemBatchConfigService.getItemBatchConfigByItemId(itemId); + if (config == null) { + throw exception(MD_ITEM_BATCH_CONFIG_NOT_EXISTS); + } + boolean hasAnyFlag = Boolean.TRUE.equals(config.getProduceDateFlag()) + || Boolean.TRUE.equals(config.getExpireDateFlag()) + || Boolean.TRUE.equals(config.getReceiptDateFlag()) + || Boolean.TRUE.equals(config.getVendorFlag()) + || Boolean.TRUE.equals(config.getClientFlag()) + || Boolean.TRUE.equals(config.getSalesOrderCodeFlag()) + || Boolean.TRUE.equals(config.getPurchaseOrderCodeFlag()) + || Boolean.TRUE.equals(config.getWorkOrderFlag()) + || Boolean.TRUE.equals(config.getTaskFlag()) + || Boolean.TRUE.equals(config.getWorkstationFlag()) + || Boolean.TRUE.equals(config.getToolFlag()) + || Boolean.TRUE.equals(config.getMoldFlag()) + || Boolean.TRUE.equals(config.getLotNumberFlag()) + || Boolean.TRUE.equals(config.getQualityStatusFlag()); + if (!hasAnyFlag) { + throw exception(MD_ITEM_BATCH_CONFIG_AT_LEAST_ONE_FLAG); + } + } + + @Override + public MesMdItemDO getItem(Long id) { + return itemMapper.selectById(id); + } + + @Override + public PageResult getItemPage(MesMdItemPageReqVO pageReqVO) { + // 查找时,如果查找某个分类编号,则包含它的子分类 + Set itemTypeIds = null; + if (pageReqVO.getItemTypeId() != null) { + itemTypeIds = new HashSet<>(); + itemTypeIds.add(pageReqVO.getItemTypeId()); + List children = itemTypeService.getItemTypeChildrenList(pageReqVO.getItemTypeId()); + itemTypeIds.addAll(convertSet(children, MesMdItemTypeDO::getId)); + } + // 分页查询 + return itemMapper.selectPage(pageReqVO, itemTypeIds); + } + + @Override + public List getItemList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return itemMapper.selectByIds(ids); + } + + @Override + public Long getItemCountByItemTypeId(Long itemTypeId) { + return itemMapper.selectCountByItemTypeId(itemTypeId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MesMdItemImportRespVO importItemList(List importItems, boolean updateSupport) { + // 1. 参数校验 + if (CollUtil.isEmpty(importItems)) { + throw exception(MD_ITEM_IMPORT_LIST_IS_EMPTY); + } + + // 2. 遍历,逐个创建 or 更新 + MesMdItemImportRespVO respVO = MesMdItemImportRespVO.builder() + .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>()) + .failureCodes(new LinkedHashMap<>()).build(); + AtomicInteger index = new AtomicInteger(1); + importItems.forEach(importItem -> { + int currentIndex = index.getAndIncrement(); + // 2.1 校验字段 + String key = StrUtil.blankToDefault(importItem.getCode(), "第 " + currentIndex + " 行"); + if (StrUtil.isBlank(importItem.getCode())) { + respVO.getFailureCodes().put(key, "物料编码不能为空"); + return; + } + if (StrUtil.isBlank(importItem.getName())) { + respVO.getFailureCodes().put(key, "物料名称不能为空"); + return; + } + if (StrUtil.isBlank(importItem.getUnitMeasureCode())) { + respVO.getFailureCodes().put(key, "单位编码不能为空"); + return; + } + // 将单位编码转换为单位 ID + MesMdUnitMeasureDO unitMeasure = unitMeasureService.getUnitMeasureByCode(importItem.getUnitMeasureCode()); + if (unitMeasure == null) { + respVO.getFailureCodes().put(key, "单位编码[" + importItem.getUnitMeasureCode() + "]不存在"); + return; + } + if (importItem.getItemTypeId() == null) { + respVO.getFailureCodes().put(key, "物料分类编号不能为空"); + return; + } + // 2.2 校验分类是否存在 + try { + validateItemTypeExists(importItem.getItemTypeId()); + } catch (ServiceException ex) { + respVO.getFailureCodes().put(key, ex.getMessage()); + return; + } + + // 2.3 判断:创建 or 更新 + MesMdItemDO existItem = itemMapper.selectByCode(importItem.getCode()); + if (existItem == null) { + // 2.3.1 创建 + try { + validateItemNameUnique(null, importItem.getName()); + } catch (ServiceException ex) { + respVO.getFailureCodes().put(key, ex.getMessage()); + return; + } + MesMdItemDO item = BeanUtils.toBean(importItem, MesMdItemDO.class); + item.setUnitMeasureId(unitMeasure.getId()); + item.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 默认禁用。信息完成后,再启用 + clearStockIfNotSafe(item); + itemMapper.insert(item); + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.ITEM.getValue(), + item.getId(), item.getCode(), item.getName()); + respVO.getCreateCodes().add(importItem.getCode()); + } else if (updateSupport) { + // 2.3.2 更新 + try { + validateItemNameUnique(existItem.getId(), importItem.getName()); + } catch (ServiceException ex) { + respVO.getFailureCodes().put(key, ex.getMessage()); + return; + } + MesMdItemDO updateObj = BeanUtils.toBean(importItem, MesMdItemDO.class); + updateObj.setId(existItem.getId()); + updateObj.setUnitMeasureId(unitMeasure.getId()); + clearStockIfNotSafe(updateObj); + itemMapper.updateById(updateObj); + respVO.getUpdateCodes().add(importItem.getCode()); + } else { + // 不支持更新 + respVO.getFailureCodes().put(key, "物料编码已存在"); + } + }); + return respVO; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeService.java new file mode 100644 index 000000000..56ca66e1c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 物料产品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdItemTypeService { + + /** + * 创建物料产品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createItemType(@Valid MesMdItemTypeSaveReqVO createReqVO); + + /** + * 更新物料产品分类 + * + * @param updateReqVO 更新信息 + */ + void updateItemType(@Valid MesMdItemTypeSaveReqVO updateReqVO); + + /** + * 删除物料产品分类 + * + * @param id 编号 + */ + void deleteItemType(Long id); + + /** + * 获得物料产品分类 + * + * @param id 编号 + * @return 物料产品分类 + */ + MesMdItemTypeDO getItemType(Long id); + + /** + * 获得物料产品分类列表 + * + * @param listReqVO 查询条件 + * @return 物料产品分类列表 + */ + List getItemTypeList(MesMdItemTypeListReqVO listReqVO); + + /** + * 获得物料产品分类列表 + * + * @param ids 编号数组 + * @return 物料产品分类列表 + */ + List getItemTypeList(Collection ids); + + /** + * 获得物料产品分类 Map + * + * @param ids 编号数组 + * @return 物料产品分类 Map + */ + default Map getItemTypeMap(Collection ids) { + return convertMap(getItemTypeList(ids), MesMdItemTypeDO::getId); + } + + /** + * 获得指定分类的所有子分类列表(递归) + * + * @param parentId 父分类编号 + * @return 子分类列表 + */ + List getItemTypeChildrenList(Long parentId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeServiceImpl.java new file mode 100644 index 000000000..b2602302b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeServiceImpl.java @@ -0,0 +1,184 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemTypeMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 物料产品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdItemTypeServiceImpl implements MesMdItemTypeService { + + @Resource + private MesMdItemTypeMapper itemTypeMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private MesMdItemService itemService; + + @Override + public Long createItemType(MesMdItemTypeSaveReqVO createReqVO) { + // 校验数据 + validateItemTypeSaveData(createReqVO); + + // 插入 + MesMdItemTypeDO itemType = BeanUtils.toBean(createReqVO, MesMdItemTypeDO.class); + itemTypeMapper.insert(itemType); + return itemType.getId(); + } + + @Override + public void updateItemType(MesMdItemTypeSaveReqVO updateReqVO) { + // 校验存在 + validateItemTypeExists(updateReqVO.getId()); + // 校验数据 + validateItemTypeSaveData(updateReqVO); + + // 更新 + MesMdItemTypeDO updateObj = BeanUtils.toBean(updateReqVO, MesMdItemTypeDO.class); + itemTypeMapper.updateById(updateObj); + } + + private void validateItemTypeSaveData(MesMdItemTypeSaveReqVO reqVO) { + // 校验父分类编号的有效性 + validateParentItemType(reqVO.getId(), reqVO.getParentId()); + // 校验分类名称的唯一性 + validateItemTypeNameUnique(reqVO.getId(), reqVO.getParentId(), reqVO.getName()); + // 校验分类编码的唯一性 + validateItemTypeCodeUnique(reqVO.getId(), reqVO.getParentId(), reqVO.getCode()); + } + + @Override + public void deleteItemType(Long id) { + // 1.1 校验存在 + validateItemTypeExists(id); + // 1.2 校验是否有子分类 + if (itemTypeMapper.selectCountByParentId(id) > 0) { + throw exception(MD_ITEM_TYPE_EXITS_CHILDREN); + } + // 1.3 校验是否有物料 + if (itemService.getItemCountByItemTypeId(id) > 0) { + throw exception(MD_ITEM_TYPE_EXITS_ITEM); + } + + // 2. 删除 + itemTypeMapper.deleteById(id); + } + + private void validateItemTypeExists(Long id) { + if (itemTypeMapper.selectById(id) == null) { + throw exception(MD_ITEM_TYPE_NOT_EXISTS); + } + } + + private void validateParentItemType(Long id, Long parentId) { + if (parentId == null || MesMdItemTypeDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父分类 + if (Objects.equals(id, parentId)) { + throw exception(MD_ITEM_TYPE_PARENT_ERROR); + } + // 2. 父分类不存在 + MesMdItemTypeDO parentItemType = itemTypeMapper.selectById(parentId); + if (parentItemType == null) { + throw exception(MD_ITEM_TYPE_PARENT_NOT_EXITS); + } + // 3. 递归校验父分类,如果父分类是自己的子分类,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentItemType.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(MD_ITEM_TYPE_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父分类 + if (parentId == null || MesMdItemTypeDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentItemType = itemTypeMapper.selectById(parentId); + if (parentItemType == null) { + break; + } + } + } + + private void validateItemTypeNameUnique(Long id, Long parentId, String name) { + MesMdItemTypeDO itemType = itemTypeMapper.selectByParentIdAndName(parentId, name); + if (itemType == null) { + return; + } + if (ObjUtil.notEqual(itemType.getId(), id)) { + throw exception(MD_ITEM_TYPE_NAME_DUPLICATE); + } + } + + private void validateItemTypeCodeUnique(Long id, Long parentId, String code) { + MesMdItemTypeDO itemType = itemTypeMapper.selectByParentIdAndCode(parentId, code); + if (itemType == null) { + return; + } + if (ObjUtil.notEqual(itemType.getId(), id)) { + throw exception(MD_ITEM_TYPE_CODE_DUPLICATE); + } + } + + @Override + public MesMdItemTypeDO getItemType(Long id) { + return itemTypeMapper.selectById(id); + } + + @Override + public List getItemTypeList(MesMdItemTypeListReqVO listReqVO) { + return itemTypeMapper.selectList(listReqVO); + } + + @Override + public List getItemTypeList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return itemTypeMapper.selectByIds(ids); + } + + @Override + public List getItemTypeChildrenList(Long parentId) { + List allList = itemTypeMapper.selectList(); // 分类总量小,全量查 + // 递归收集所有子分类 + List result = new ArrayList<>(); + collectItemTypeChildren(result, parentId, allList); + return result; + } + + /** + * 递归收集所有子分类 + */ + private void collectItemTypeChildren(List result, Long parentId, List allList) { + for (MesMdItemTypeDO itemType : allList) { + if (Objects.equals(itemType.getParentId(), parentId)) { + result.add(itemType); + collectItemTypeChildren(result, itemType.getId(), allList); + } + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductBomService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductBomService.java new file mode 100644 index 000000000..cb044054a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductBomService.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * MES 产品BOM Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdProductBomService { + + /** + * 创建产品BOM + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductBom(@Valid MesMdProductBomSaveReqVO createReqVO); + + /** + * 更新产品BOM + * + * @param updateReqVO 更新信息 + */ + void updateProductBom(@Valid MesMdProductBomSaveReqVO updateReqVO); + + /** + * 删除产品BOM + * + * @param id 编号 + */ + void deleteProductBom(Long id); + + /** + * 获得产品BOM + * + * @param id 编号 + * @return 产品BOM + */ + MesMdProductBomDO getProductBom(Long id); + + /** + * 获得产品BOM分页 + * + * @param pageReqVO 分页查询 + * @return 产品BOM分页 + */ + PageResult getProductBomPage(MesMdProductBomPageReqVO pageReqVO); + + /** + * 根据物料产品编号获得产品BOM列表 + * + * @param itemId 物料产品编号 + * @return 产品BOM列表 + */ + List getProductBomListByItemId(Long itemId); + + /** + * 根据物料产品编号批量获得产品BOM列表 + * + * @param itemIds 物料产品编号数组 + * @return 产品BOM列表 + */ + List getProductBomListByItemIds(Collection itemIds); + + /** + * 根据物料产品编号删除产品BOM + * + * @param itemId 物料产品编号 + */ + void deleteProductBomByItemId(Long itemId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductBomServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductBomServiceImpl.java new file mode 100644 index 000000000..eba2be7f0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductBomServiceImpl.java @@ -0,0 +1,144 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdProductBomMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap2; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 产品BOM Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdProductBomServiceImpl implements MesMdProductBomService { + + @Resource + private MesMdProductBomMapper productBomMapper; + + @Resource + @Lazy // 避免循环依赖 + private MesMdItemService itemService; + + @Override + public Long createProductBom(MesMdProductBomSaveReqVO createReqVO) { + // 1.1 校验数据 + validateProductBomSaveData(createReqVO); + // 1.2 校验不能形成闭环 + if (hasBomCycle(createReqVO.getItemId(), createReqVO.getBomItemId())) { + throw exception(MD_PRODUCT_BOM_CIRCULAR); + } + + // 2. 插入 + MesMdProductBomDO productBom = BeanUtils.toBean(createReqVO, MesMdProductBomDO.class); + productBomMapper.insert(productBom); + return productBom.getId(); + } + + @Override + public void updateProductBom(MesMdProductBomSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateProductBomExists(updateReqVO.getId()); + // 1.2 校验数据 + validateProductBomSaveData(updateReqVO); + + // 更新 + MesMdProductBomDO updateObj = BeanUtils.toBean(updateReqVO, MesMdProductBomDO.class); + productBomMapper.updateById(updateObj); + } + + private void validateProductBomSaveData(MesMdProductBomSaveReqVO reqVO) { + // 校验物料产品存在 + validateItemExists(reqVO.getItemId()); + // 校验BOM物料存在 + validateItemExists(reqVO.getBomItemId()); + // 校验不能自引用 + if (reqVO.getItemId().equals(reqVO.getBomItemId())) { + throw exception(MD_PRODUCT_BOM_SELF_REFERENCE); + } + } + + @Override + public void deleteProductBom(Long id) { + // 校验存在 + validateProductBomExists(id); + // 删除 + productBomMapper.deleteById(id); + } + + private void validateProductBomExists(Long id) { + if (productBomMapper.selectById(id) == null) { + throw exception(MD_PRODUCT_BOM_NOT_EXISTS); + } + } + + private void validateItemExists(Long itemId) { + if (itemService.getItem(itemId) == null) { + throw exception(MD_ITEM_NOT_EXISTS); + } + } + + /** + * 检测新增边 (itemId -> bomItemId) 后,BOM 图是否存在闭环 + * + * @param itemId 父物料编号 + * @param bomItemId BOM子物料编号 + * @return 是否存在闭环 + */ + private boolean hasBomCycle(Long itemId, Long bomItemId) { + // 1.1 获取所有已有的 BOM 记录 + List allBoms = productBomMapper.selectAll(); + // 1.2 构建邻接表:parent -> Set + Map> graph = convertMultiMap2(allBoms, + MesMdProductBomDO::getItemId, MesMdProductBomDO::getBomItemId); + // 1.3 添加待新增的边 + graph.computeIfAbsent(itemId, k -> new HashSet<>()).add(bomItemId); + // 2. DFS 检测环 + for (Long node : graph.keySet()) { + if (CollectionUtils.dfs(node, graph)) { + return true; + } + } + return false; + } + + @Override + public MesMdProductBomDO getProductBom(Long id) { + return productBomMapper.selectById(id); + } + + @Override + public PageResult getProductBomPage(MesMdProductBomPageReqVO pageReqVO) { + return productBomMapper.selectPage(pageReqVO); + } + + @Override + public List getProductBomListByItemId(Long itemId) { + return productBomMapper.selectByItemId(itemId); + } + + @Override + public List getProductBomListByItemIds(Collection itemIds) { + return productBomMapper.selectByItemIds(itemIds); + } + + @Override + public void deleteProductBomByItemId(Long itemId) { + productBomMapper.deleteByItemId(itemId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipService.java new file mode 100644 index 000000000..322bec692 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipService.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip.MesMdProductSipPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip.MesMdProductSipSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductSipDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 产品SIP Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdProductSipService { + + /** + * 创建产品SIP + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductSip(@Valid MesMdProductSipSaveReqVO createReqVO); + + /** + * 更新产品SIP + * + * @param updateReqVO 更新信息 + */ + void updateProductSip(@Valid MesMdProductSipSaveReqVO updateReqVO); + + /** + * 删除产品SIP + * + * @param id 编号 + */ + void deleteProductSip(Long id); + + /** + * 获得产品SIP + * + * @param id 编号 + * @return 产品SIP + */ + MesMdProductSipDO getProductSip(Long id); + + /** + * 获得产品SIP分页 + * + * @param pageReqVO 分页查询 + * @return 产品SIP分页 + */ + PageResult getProductSipPage(MesMdProductSipPageReqVO pageReqVO); + + /** + * 根据物料产品编号,获得产品SIP列表 + * + * @param itemId 物料产品编号 + * @return 产品SIP列表 + */ + List getProductSipListByItemId(Long itemId); + + /** + * 根据物料产品编号,删除产品SIP + * + * @param itemId 物料产品编号 + */ + void deleteProductSipByItemId(Long itemId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipServiceImpl.java new file mode 100644 index 000000000..f6963e340 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipServiceImpl.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip.MesMdProductSipPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sip.MesMdProductSipSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductSipDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdProductSipMapper; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 产品SIP Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdProductSipServiceImpl implements MesMdProductSipService { + + @Resource + private MesMdProductSipMapper productSipMapper; + + @Resource + private MesProProcessService processService; + + @Override + public Long createProductSip(MesMdProductSipSaveReqVO createReqVO) { + // 校验数据 + validateProductSipSaveData(createReqVO, null); + + // 插入 + MesMdProductSipDO sip = BeanUtils.toBean(createReqVO, MesMdProductSipDO.class); + productSipMapper.insert(sip); + return sip.getId(); + } + + @Override + public void updateProductSip(MesMdProductSipSaveReqVO updateReqVO) { + // 校验存在 + validateProductSipExists(updateReqVO.getId()); + // 校验数据 + validateProductSipSaveData(updateReqVO, updateReqVO.getId()); + + // 更新 + MesMdProductSipDO updateObj = BeanUtils.toBean(updateReqVO, MesMdProductSipDO.class); + productSipMapper.updateById(updateObj); + } + + private void validateProductSipSaveData(MesMdProductSipSaveReqVO reqVO, Long excludeId) { + // 校验排列顺序的唯一性 + validateSortUnique(reqVO.getItemId(), reqVO.getSort(), excludeId); + // 校验工序存在 + if (reqVO.getProcessId() != null) { + processService.validateProcessExists(reqVO.getProcessId()); + } + } + + @Override + public void deleteProductSip(Long id) { + // 校验存在 + validateProductSipExists(id); + // 删除 + productSipMapper.deleteById(id); + } + + private void validateProductSipExists(Long id) { + if (productSipMapper.selectById(id) == null) { + throw exception(MD_PRODUCT_SIP_NOT_EXISTS); + } + } + + private void validateSortUnique(Long itemId, Integer sort, Long excludeId) { + Long count = productSipMapper.selectCountByItemIdAndSort(itemId, sort, excludeId); + if (count > 0) { + throw exception(MD_PRODUCT_SIP_SORT_DUPLICATE); + } + } + + @Override + public MesMdProductSipDO getProductSip(Long id) { + return productSipMapper.selectById(id); + } + + @Override + public PageResult getProductSipPage(MesMdProductSipPageReqVO pageReqVO) { + return productSipMapper.selectPage(pageReqVO); + } + + @Override + public List getProductSipListByItemId(Long itemId) { + return productSipMapper.selectByItemId(itemId); + } + + @Override + public void deleteProductSipByItemId(Long itemId) { + productSipMapper.deleteByItemId(itemId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopService.java new file mode 100644 index 000000000..32e46dacd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopService.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop.MesMdProductSopPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop.MesMdProductSopSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductSopDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 产品SOP Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdProductSopService { + + /** + * 创建产品SOP + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductSop(@Valid MesMdProductSopSaveReqVO createReqVO); + + /** + * 更新产品SOP + * + * @param updateReqVO 更新信息 + */ + void updateProductSop(@Valid MesMdProductSopSaveReqVO updateReqVO); + + /** + * 删除产品SOP + * + * @param id 编号 + */ + void deleteProductSop(Long id); + + /** + * 获得产品SOP + * + * @param id 编号 + * @return 产品SOP + */ + MesMdProductSopDO getProductSop(Long id); + + /** + * 获得产品SOP分页 + * + * @param pageReqVO 分页查询 + * @return 产品SOP分页 + */ + PageResult getProductSopPage(MesMdProductSopPageReqVO pageReqVO); + + /** + * 根据物料产品编号,获得产品SOP列表 + * + * @param itemId 物料产品编号 + * @return 产品SOP列表 + */ + List getProductSopListByItemId(Long itemId); + + /** + * 根据物料产品编号,删除产品SOP + * + * @param itemId 物料产品编号 + */ + void deleteProductSopByItemId(Long itemId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopServiceImpl.java new file mode 100644 index 000000000..3bbd330b7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopServiceImpl.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop.MesMdProductSopPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.sop.MesMdProductSopSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductSopDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdProductSopMapper; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 产品SOP Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdProductSopServiceImpl implements MesMdProductSopService { + + @Resource + private MesMdProductSopMapper productSopMapper; + + @Resource + private MesProProcessService processService; + + @Override + public Long createProductSop(MesMdProductSopSaveReqVO createReqVO) { + // 校验数据 + validateProductSopSaveData(createReqVO, null); + + // 插入 + MesMdProductSopDO sop = BeanUtils.toBean(createReqVO, MesMdProductSopDO.class); + productSopMapper.insert(sop); + return sop.getId(); + } + + @Override + public void updateProductSop(MesMdProductSopSaveReqVO updateReqVO) { + // 校验存在 + validateProductSopExists(updateReqVO.getId()); + // 校验数据 + validateProductSopSaveData(updateReqVO, updateReqVO.getId()); + + // 更新 + MesMdProductSopDO updateObj = BeanUtils.toBean(updateReqVO, MesMdProductSopDO.class); + productSopMapper.updateById(updateObj); + } + + private void validateProductSopSaveData(MesMdProductSopSaveReqVO reqVO, Long excludeId) { + // 校验排列顺序的唯一性 + validateSortUnique(reqVO.getItemId(), reqVO.getSort(), excludeId); + // 校验工序存在 + if (reqVO.getProcessId() != null) { + processService.validateProcessExists(reqVO.getProcessId()); + } + } + + @Override + public void deleteProductSop(Long id) { + // 校验存在 + validateProductSopExists(id); + // 删除 + productSopMapper.deleteById(id); + } + + private void validateProductSopExists(Long id) { + if (productSopMapper.selectById(id) == null) { + throw exception(MD_PRODUCT_SOP_NOT_EXISTS); + } + } + + private void validateSortUnique(Long itemId, Integer sort, Long excludeId) { + Long count = productSopMapper.selectCountByItemIdAndSort(itemId, sort, excludeId); + if (count > 0) { + throw exception(MD_PRODUCT_SOP_SORT_DUPLICATE); + } + } + + @Override + public MesMdProductSopDO getProductSop(Long id) { + return productSopMapper.selectById(id); + } + + @Override + public PageResult getProductSopPage(MesMdProductSopPageReqVO pageReqVO) { + return productSopMapper.selectPage(pageReqVO); + } + + @Override + public List getProductSopListByItemId(Long itemId) { + return productSopMapper.selectByItemId(itemId); + } + + @Override + public void deleteProductSopByItemId(Long itemId) { + productSopMapper.deleteByItemId(itemId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureService.java new file mode 100644 index 000000000..eb38c2b10 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureService.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.mes.service.md.unitmeasure; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasurePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasureSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 计量单位 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdUnitMeasureService { + + /** + * 创建计量单位 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createUnitMeasure(@Valid MesMdUnitMeasureSaveReqVO createReqVO); + + /** + * 更新计量单位 + * + * @param updateReqVO 更新信息 + */ + void updateUnitMeasure(@Valid MesMdUnitMeasureSaveReqVO updateReqVO); + + /** + * 删除计量单位 + * + * @param id 编号 + */ + void deleteUnitMeasure(Long id); + + /** + * 获得计量单位 + * + * @param id 编号 + * @return 计量单位 + */ + MesMdUnitMeasureDO getUnitMeasure(Long id); + + /** + * 获得计量单位分页 + * + * @param pageReqVO 分页查询 + * @return 计量单位分页 + */ + PageResult getUnitMeasurePage(MesMdUnitMeasurePageReqVO pageReqVO); + + /** + * 获得指定状态的计量单位列表 + * + * @param status 状态 + * @return 计量单位列表 + */ + List getUnitMeasureListByStatus(Integer status); + + /** + * 获得计量单位列表 + * + * @param ids 编号数组 + * @return 计量单位列表 + */ + List getUnitMeasureList(Collection ids); + + /** + * 获得计量单位 Map + * + * @param ids 编号数组 + * @return 计量单位 Map + */ + default Map getUnitMeasureMap(Collection ids) { + return convertMap(getUnitMeasureList(ids), MesMdUnitMeasureDO::getId); + } + + /** + * 根据编码获得计量单位 + * + * @param code 单位编码 + * @return 计量单位 + */ + MesMdUnitMeasureDO getUnitMeasureByCode(String code); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureServiceImpl.java new file mode 100644 index 000000000..1d90ae3a5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureServiceImpl.java @@ -0,0 +1,121 @@ +package cn.iocoder.yudao.module.mes.service.md.unitmeasure; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasurePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasureSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.md.unitmeasure.MesMdUnitMeasureMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 计量单位 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdUnitMeasureServiceImpl implements MesMdUnitMeasureService { + + @Resource + private MesMdUnitMeasureMapper unitMeasureMapper; + + @Resource + private MesMdItemMapper itemMapper; + + @Override + public Long createUnitMeasure(MesMdUnitMeasureSaveReqVO createReqVO) { + // 校验编码唯一 + validateUnitMeasureCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesMdUnitMeasureDO unitMeasure = BeanUtils.toBean(createReqVO, MesMdUnitMeasureDO.class); + unitMeasureMapper.insert(unitMeasure); + return unitMeasure.getId(); + } + + @Override + public void updateUnitMeasure(MesMdUnitMeasureSaveReqVO updateReqVO) { + // 校验存在 + validateUnitMeasureExists(updateReqVO.getId()); + // 校验编码唯一 + validateUnitMeasureCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesMdUnitMeasureDO updateObj = BeanUtils.toBean(updateReqVO, MesMdUnitMeasureDO.class); + unitMeasureMapper.updateById(updateObj); + } + + @Override + public void deleteUnitMeasure(Long id) { + // 校验存在 + validateUnitMeasureExists(id); + // 校验是否被物料引用 + if (itemMapper.selectCountByUnitMeasureId(id) > 0) { + throw exception(MD_UNIT_MEASURE_HAS_ITEM); + } + // 删除 + unitMeasureMapper.deleteById(id); + } + + private void validateUnitMeasureExists(Long id) { + if (unitMeasureMapper.selectById(id) == null) { + throw exception(MD_UNIT_MEASURE_NOT_EXISTS); + } + } + + private void validateUnitMeasureCodeUnique(Long id, String code) { + MesMdUnitMeasureDO unitMeasure = unitMeasureMapper.selectByCode(code); + if (unitMeasure == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的记录 + if (id == null) { + throw exception(MD_UNIT_MEASURE_CODE_DUPLICATE); + } + if (!Objects.equals(unitMeasure.getId(), id)) { + throw exception(MD_UNIT_MEASURE_CODE_DUPLICATE); + } + } + + @Override + public MesMdUnitMeasureDO getUnitMeasure(Long id) { + return unitMeasureMapper.selectById(id); + } + + @Override + public PageResult getUnitMeasurePage(MesMdUnitMeasurePageReqVO pageReqVO) { + return unitMeasureMapper.selectPage(pageReqVO); + } + + @Override + public List getUnitMeasureListByStatus(Integer status) { + return unitMeasureMapper.selectListByStatus(status); + } + + @Override + public List getUnitMeasureList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return unitMeasureMapper.selectByIds(ids); + } + + @Override + public MesMdUnitMeasureDO getUnitMeasureByCode(String code) { + return unitMeasureMapper.selectByCode(code); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorService.java new file mode 100644 index 000000000..4e86e4b52 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorService.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.mes.service.md.vendor; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 供应商 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdVendorService { + + /** + * 创建供应商 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createVendor(@Valid MesMdVendorSaveReqVO createReqVO); + + /** + * 更新供应商 + * + * @param updateReqVO 更新信息 + */ + void updateVendor(@Valid MesMdVendorSaveReqVO updateReqVO); + + /** + * 删除供应商 + * + * @param id 编号 + */ + void deleteVendor(Long id); + + /** + * 获得供应商 + * + * @param id 编号 + * @return 供应商 + */ + MesMdVendorDO getVendor(Long id); + + /** + * 校验供应商存在 + * + * @param id 供应商 ID + * @return 供应商 + */ + MesMdVendorDO validateVendorExists(Long id); + + /** + * 获得供应商分页 + * + * @param pageReqVO 分页查询 + * @return 供应商分页 + */ + PageResult getVendorPage(MesMdVendorPageReqVO pageReqVO); + + /** + * 获得供应商列表 + * + * @param ids 编号列表 + * @return 供应商列表 + */ + List getVendorList(Collection ids); + + /** + * 获得供应商 Map + * + * @param ids 编号列表 + * @return 供应商 Map + */ + default Map getVendorMap(Collection ids) { + return convertMap(getVendorList(ids), MesMdVendorDO::getId); + } + + /** + * 批量导入供应商 + * + * @param importVendors 导入供应商列表 + * @param updateSupport 是否支持更新 + * @return 导入结果 + */ + MesMdVendorImportRespVO importVendorList(List importVendors, boolean updateSupport); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorServiceImpl.java new file mode 100644 index 000000000..d1baab9de --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorServiceImpl.java @@ -0,0 +1,238 @@ +package cn.iocoder.yudao.module.mes.service.md.vendor; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorImportExcelVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorImportRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.vendor.MesMdVendorMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import cn.iocoder.yudao.module.mes.service.wm.itemreceipt.MesWmItemReceiptService; +import cn.iocoder.yudao.module.mes.service.wm.returnvendor.MesWmReturnVendorService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 供应商 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdVendorServiceImpl implements MesMdVendorService { + + @Resource + private MesMdVendorMapper vendorMapper; + + @Resource + private MesWmBarcodeService barcodeService; + @Resource + @Lazy + private MesWmItemReceiptService itemReceiptService; + @Resource + @Lazy + private MesWmArrivalNoticeService arrivalNoticeService; + @Resource + @Lazy + private MesWmReturnVendorService returnVendorService; + + @Override + public Long createVendor(MesMdVendorSaveReqVO createReqVO) { + // 校验数据 + validateVendorSaveData(createReqVO); + + // 插入 + MesMdVendorDO vendor = BeanUtils.toBean(createReqVO, MesMdVendorDO.class); + vendorMapper.insert(vendor); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.VENDOR.getValue(), + vendor.getId(), vendor.getCode(), vendor.getName()); + return vendor.getId(); + } + + @Override + public void updateVendor(MesMdVendorSaveReqVO updateReqVO) { + // 校验存在 + validateVendorExists(updateReqVO.getId()); + // 校验数据 + validateVendorSaveData(updateReqVO); + + // 更新 + MesMdVendorDO updateObj = BeanUtils.toBean(updateReqVO, MesMdVendorDO.class); + vendorMapper.updateById(updateObj); + } + + @Override + public void deleteVendor(Long id) { + // 校验存在 + validateVendorExists(id); + // 校验是否被其他业务引用 + validateVendorNotReferenced(id); + // 删除 + vendorMapper.deleteById(id); + } + + @Override + public MesMdVendorDO validateVendorExists(Long id) { + MesMdVendorDO vendor = vendorMapper.selectById(id); + if (vendor == null) { + throw exception(MD_VENDOR_NOT_EXISTS); + } + return vendor; + } + + private void validateVendorSaveData(MesMdVendorSaveReqVO reqVO) { + // 校验编码唯一 + validateVendorCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验名称唯一 + validateVendorNameUnique(reqVO.getId(), reqVO.getName()); + // 校验简称唯一 + validateVendorNicknameUnique(reqVO.getId(), reqVO.getNickname()); + } + + private void validateVendorCodeUnique(Long id, String code) { + MesMdVendorDO vendor = vendorMapper.selectByCode(code); + if (vendor == null) { + return; + } + if (ObjUtil.notEqual(vendor.getId(), id)) { + throw exception(MD_VENDOR_CODE_DUPLICATE); + } + } + + private void validateVendorNameUnique(Long id, String name) { + MesMdVendorDO vendor = vendorMapper.selectByName(name); + if (vendor == null) { + return; + } + if (ObjUtil.notEqual(vendor.getId(), id)) { + throw exception(MD_VENDOR_NAME_DUPLICATE); + } + } + + private void validateVendorNicknameUnique(Long id, String nickname) { + if (StrUtil.isEmpty(nickname)) { + return; + } + MesMdVendorDO vendor = vendorMapper.selectByNickname(nickname); + if (vendor == null) { + return; + } + if (ObjUtil.notEqual(vendor.getId(), id)) { + throw exception(MD_VENDOR_NICKNAME_DUPLICATE); + } + } + + private void validateVendorNotReferenced(Long id) { + if (itemReceiptService.getItemReceiptCountByVendorId(id) > 0 + || arrivalNoticeService.getArrivalNoticeCountByVendorId(id) > 0 + || returnVendorService.getReturnVendorCountByVendorId(id) > 0) { + throw exception(MD_VENDOR_HAS_REFERENCE); + } + } + + @Override + public MesMdVendorDO getVendor(Long id) { + return vendorMapper.selectById(id); + } + + @Override + public PageResult getVendorPage(MesMdVendorPageReqVO pageReqVO) { + return vendorMapper.selectPage(pageReqVO); + } + + @Override + public List getVendorList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return vendorMapper.selectByIds(ids); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MesMdVendorImportRespVO importVendorList(List importVendors, boolean updateSupport) { + // 1. 参数校验 + if (CollUtil.isEmpty(importVendors)) { + throw exception(MD_VENDOR_IMPORT_LIST_IS_EMPTY); + } + + // 2. 遍历,逐个创建 or 更新 + MesMdVendorImportRespVO respVO = MesMdVendorImportRespVO.builder() + .createCodes(new ArrayList<>()).updateCodes(new ArrayList<>()) + .failureCodes(new LinkedHashMap<>()).build(); + AtomicInteger index = new AtomicInteger(1); + importVendors.forEach(importVendor -> { + int currentIndex = index.getAndIncrement(); + // 2.1 校验字段 + String key = StrUtil.blankToDefault(importVendor.getCode(), "第 " + currentIndex + " 行"); + if (StrUtil.isBlank(importVendor.getCode())) { + respVO.getFailureCodes().put(key, "供应商编码不能为空"); + return; + } + if (StrUtil.isBlank(importVendor.getName())) { + respVO.getFailureCodes().put(key, "供应商名称不能为空"); + return; + } + + // 2.2 判断:创建 or 更新 + MesMdVendorDO existVendor = vendorMapper.selectByCode(importVendor.getCode()); + if (existVendor == null) { + // 2.2.1 创建 + try { + validateVendorNameUnique(null, importVendor.getName()); + validateVendorNicknameUnique(null, importVendor.getNickname()); + } catch (ServiceException ex) { + respVO.getFailureCodes().put(key, ex.getMessage()); + return; + } + MesMdVendorDO vendor = BeanUtils.toBean(importVendor, MesMdVendorDO.class); + vendorMapper.insert(vendor); + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.VENDOR.getValue(), + vendor.getId(), vendor.getCode(), vendor.getName()); + respVO.getCreateCodes().add(importVendor.getCode()); + } else if (updateSupport) { + // 2.2.2 更新 + try { + validateVendorNameUnique(existVendor.getId(), importVendor.getName()); + validateVendorNicknameUnique(existVendor.getId(), importVendor.getNickname()); + } catch (ServiceException ex) { + respVO.getFailureCodes().put(key, ex.getMessage()); + return; + } + MesMdVendorDO updateObj = BeanUtils.toBean(importVendor, MesMdVendorDO.class); + updateObj.setId(existVendor.getId()); + vendorMapper.updateById(updateObj); + respVO.getUpdateCodes().add(importVendor.getCode()); + } else { + // 不支持更新 + respVO.getFailureCodes().put(key, "供应商编码已存在"); + } + }); + return respVO; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopService.java new file mode 100644 index 000000000..6ca847707 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopService.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 车间 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdWorkshopService { + + /** + * 创建车间 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkshop(@Valid MesMdWorkshopSaveReqVO createReqVO); + + /** + * 更新车间 + * + * @param updateReqVO 更新信息 + */ + void updateWorkshop(@Valid MesMdWorkshopSaveReqVO updateReqVO); + + /** + * 删除车间 + * + * @param id 编号 + */ + void deleteWorkshop(Long id); + + /** + * 获得车间 + * + * @param id 编号 + * @return 车间 + */ + MesMdWorkshopDO getWorkshop(Long id); + + /** + * 获得车间分页 + * + * @param pageReqVO 分页查询 + * @return 车间分页 + */ + PageResult getWorkshopPage(MesMdWorkshopPageReqVO pageReqVO); + + /** + * 获得车间列表 + * + * @param ids 编号列表 + * @return 车间列表 + */ + List getWorkshopList(Collection ids); + + /** + * 获得车间 Map + * + * @param ids 编号列表 + * @return 车间 Map + */ + default Map getWorkshopMap(Collection ids) { + return convertMap(getWorkshopList(ids), MesMdWorkshopDO::getId); + } + + /** + * 获得指定状态的车间列表 + * + * @param status 状态 + * @return 车间列表 + */ + List getWorkshopListByStatus(Integer status); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopServiceImpl.java new file mode 100644 index 000000000..e54f88afc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopServiceImpl.java @@ -0,0 +1,140 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkshopMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 车间 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdWorkshopServiceImpl implements MesMdWorkshopService { + + @Resource + private MesMdWorkshopMapper workshopMapper; + + @Resource + @Lazy + private MesMdWorkstationMapper workstationMapper; + + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createWorkshop(MesMdWorkshopSaveReqVO createReqVO) { + // 校验编码唯一 + validateWorkshopCodeUnique(null, createReqVO.getCode()); + // 校验名称唯一 + validateWorkshopNameUnique(null, createReqVO.getName()); + + // 插入 + MesMdWorkshopDO workshop = BeanUtils.toBean(createReqVO, MesMdWorkshopDO.class); + workshopMapper.insert(workshop); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.WORKSHOP.getValue(), + workshop.getId(), workshop.getCode(), workshop.getName()); + return workshop.getId(); + } + + @Override + public void updateWorkshop(MesMdWorkshopSaveReqVO updateReqVO) { + // 校验存在 + validateWorkshopExists(updateReqVO.getId()); + // 校验编码唯一 + validateWorkshopCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + // 校验名称唯一 + validateWorkshopNameUnique(updateReqVO.getId(), updateReqVO.getName()); + + // 更新 + MesMdWorkshopDO updateObj = BeanUtils.toBean(updateReqVO, MesMdWorkshopDO.class); + workshopMapper.updateById(updateObj); + } + + @Override + public void deleteWorkshop(Long id) { + // 校验存在 + validateWorkshopExists(id); + // 校验车间下是否存在工作站 + Long count = workstationMapper.selectCount(MesMdWorkstationDO::getWorkshopId, id); + if (count > 0) { + throw exception(MD_WORKSHOP_HAS_WORKSTATION); + } + + // 删除 + workshopMapper.deleteById(id); + } + + private void validateWorkshopExists(Long id) { + if (workshopMapper.selectById(id) == null) { + throw exception(MD_WORKSHOP_NOT_EXISTS); + } + } + + private void validateWorkshopCodeUnique(Long id, String code) { + MesMdWorkshopDO workshop = workshopMapper.selectByCode(code); + if (workshop == null) { + return; + } + if (ObjUtil.notEqual(workshop.getId(), id)) { + throw exception(MD_WORKSHOP_CODE_DUPLICATE); + } + } + + private void validateWorkshopNameUnique(Long id, String name) { + MesMdWorkshopDO workshop = workshopMapper.selectByName(name); + if (workshop == null) { + return; + } + if (ObjUtil.notEqual(workshop.getId(), id)) { + throw exception(MD_WORKSHOP_NAME_DUPLICATE); + } + } + + @Override + public MesMdWorkshopDO getWorkshop(Long id) { + return workshopMapper.selectById(id); + } + + @Override + public PageResult getWorkshopPage(MesMdWorkshopPageReqVO pageReqVO) { + return workshopMapper.selectPage(pageReqVO); + } + + @Override + public List getWorkshopList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return workshopMapper.selectByIds(ids); + } + + @Override + public List getWorkshopListByStatus(Integer status) { + return workshopMapper.selectListByStatus(status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineService.java new file mode 100644 index 000000000..9352feba7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineService.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.machine.MesMdWorkstationMachineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationMachineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 设备资源 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdWorkstationMachineService { + + /** + * 创建设备资源 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkstationMachine(@Valid MesMdWorkstationMachineSaveReqVO createReqVO); + + /** + * 删除设备资源 + * + * @param id 编号 + */ + void deleteWorkstationMachine(Long id); + + /** + * 获得设备资源列表 + * + * @param workstationId 工作站编号 + * @return 设备资源列表 + */ + List getWorkstationMachineListByWorkstationId(Long workstationId); + + /** + * 按工作站编号删除设备资源(级联删除) + * + * @param workstationId 工作站编号 + */ + void deleteWorkstationMachineByWorkstationId(Long workstationId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineServiceImpl.java new file mode 100644 index 000000000..9ac239f9c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineServiceImpl.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.machine.MesMdWorkstationMachineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationMachineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationMachineMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationMapper; +import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 设备资源 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdWorkstationMachineServiceImpl implements MesMdWorkstationMachineService { + + @Resource + private MesMdWorkstationMachineMapper workstationMachineMapper; + + @Resource + private MesMdWorkstationMapper workstationMapper; + + @Resource + private MesDvMachineryService machineryService; + + @Override + public Long createWorkstationMachine(MesMdWorkstationMachineSaveReqVO createReqVO) { + // 校验数据 + validateWorkstationMachineSaveData(createReqVO); + + // 插入 + MesMdWorkstationMachineDO machine = BeanUtils.toBean(createReqVO, MesMdWorkstationMachineDO.class); + workstationMachineMapper.insert(machine); + return machine.getId(); + } + + private void validateWorkstationMachineSaveData(MesMdWorkstationMachineSaveReqVO reqVO) { + // 校验设备是否存在 + machineryService.validateMachineryExists(reqVO.getMachineryId()); + // 校验该设备是否已分配到其他工作站(一台设备只能分配到一个工作站) + MesMdWorkstationMachineDO existing = workstationMachineMapper.selectByMachineryId(reqVO.getMachineryId()); + if (existing != null) { + MesMdWorkstationDO workstation = workstationMapper.selectById(existing.getWorkstationId()); + throw exception(MD_WORKSTATION_MACHINE_EXISTS, + workstation != null ? workstation.getName() : String.valueOf(existing.getWorkstationId())); + } + } + + @Override + public void deleteWorkstationMachine(Long id) { + if (workstationMachineMapper.selectById(id) == null) { + throw exception(MD_WORKSTATION_MACHINE_NOT_EXISTS); + } + workstationMachineMapper.deleteById(id); + } + + @Override + public List getWorkstationMachineListByWorkstationId(Long workstationId) { + return workstationMachineMapper.selectListByWorkstationId(workstationId); + } + + @Override + public void deleteWorkstationMachineByWorkstationId(Long workstationId) { + workstationMachineMapper.deleteByWorkstationId(workstationId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationService.java new file mode 100644 index 000000000..752796259 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationService.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 工作站 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdWorkstationService { + + /** + * 创建工作站 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkstation(@Valid MesMdWorkstationSaveReqVO createReqVO); + + /** + * 更新工作站 + * + * @param updateReqVO 更新信息 + */ + void updateWorkstation(@Valid MesMdWorkstationSaveReqVO updateReqVO); + + /** + * 删除工作站 + * + * @param id 编号 + */ + void deleteWorkstation(Long id); + + /** + * 校验工作站存在 + * + * @param id 编号 + * @return 工作站 + */ + MesMdWorkstationDO validateWorkstationExists(Long id); + + /** + * 获得工作站 + * + * @param id 编号 + * @return 工作站 + */ + MesMdWorkstationDO getWorkstation(Long id); + + /** + * 获得工作站分页 + * + * @param pageReqVO 分页查询 + * @return 工作站分页 + */ + PageResult getWorkstationPage(MesMdWorkstationPageReqVO pageReqVO); + + /** + * 获得指定状态的工作站列表 + * + * @param status 状态 + * @return 工作站列表 + */ + List getWorkstationListByStatus(Integer status); + + /** + * 获得指定仓库下的工作站数量 + * + * @param warehouseId 仓库编号 + * @return 工作站数量 + */ + Long getWorkstationCountByWarehouseId(Long warehouseId); + + /** + * 获得指定库区下的工作站数量 + * + * @param locationId 库区编号 + * @return 工作站数量 + */ + Long getWorkstationCountByLocationId(Long locationId); + + /** + * 获得指定库位下的工作站数量 + * + * @param areaId 库位编号 + * @return 工作站数量 + */ + Long getWorkstationCountByAreaId(Long areaId); + + /** + * 获得工作站列表 + * + * @param ids 编号数组 + * @return 工作站列表 + */ + List getWorkstationList(Collection ids); + + /** + * 获得工作站 Map + * + * @param ids 编号数组 + * @return 工作站 Map + */ + default Map getWorkstationMap(Collection ids) { + return convertMap(getWorkstationList(ids), MesMdWorkstationDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationServiceImpl.java new file mode 100644 index 000000000..5b2dbc8f8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationServiceImpl.java @@ -0,0 +1,258 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 工作站 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdWorkstationServiceImpl implements MesMdWorkstationService { + + @Resource + private MesMdWorkstationMapper workstationMapper; + + @Resource + private MesMdWorkstationMachineService workstationMachineService; + @Resource + private MesMdWorkstationToolService workstationToolService; + @Resource + private MesMdWorkstationWorkerService workstationWorkerService; + + @Resource + private MesMdWorkshopService workshopService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + @Resource + private MesWmBarcodeService barcodeService; + @Resource + private MesProProcessService processService; + + @Override + public Long createWorkstation(MesMdWorkstationSaveReqVO createReqVO) { + // 校验数据 + validateWorkstationSaveData(null, createReqVO); + + // 插入 + MesMdWorkstationDO workstation = BeanUtils.toBean(createReqVO, MesMdWorkstationDO.class); + workstationMapper.insert(workstation); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.WORKSTATION.getValue(), + workstation.getId(), workstation.getCode(), workstation.getName()); + return workstation.getId(); + } + + @Override + public void updateWorkstation(MesMdWorkstationSaveReqVO updateReqVO) { + // 校验存在 + validateWorkstationExists(updateReqVO.getId()); + // 校验数据 + validateWorkstationSaveData(updateReqVO.getId(), updateReqVO); + + // 更新 + MesMdWorkstationDO updateObj = BeanUtils.toBean(updateReqVO, MesMdWorkstationDO.class); + workstationMapper.updateById(updateObj); + } + + private void validateWorkstationSaveData(Long id, MesMdWorkstationSaveReqVO reqVO) { + // 校验编码唯一 + validateWorkstationCodeUnique(id, reqVO.getCode()); + // 校验名称唯一 + validateWorkstationNameUnique(id, reqVO.getName()); + // 校验车间存在 + validateWorkshopExists(reqVO.getWorkshopId()); + // 校验工序存在 + processService.validateProcessExists(reqVO.getProcessId()); + // 处理仓库层级(未指定仓库时自动设置虚拟线边库) + handleWarehouseHierarchy(reqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteWorkstation(Long id) { + // 校验存在 + validateWorkstationExists(id); + + // 级联删除子资源 + workstationMachineService.deleteWorkstationMachineByWorkstationId(id); + workstationToolService.deleteWorkstationToolByWorkstationId(id); + workstationWorkerService.deleteWorkstationWorkerByWorkstationId(id); + // 删除工作站 + workstationMapper.deleteById(id); + } + + @Override + public MesMdWorkstationDO validateWorkstationExists(Long id) { + MesMdWorkstationDO workstation = workstationMapper.selectById(id); + if (workstation == null) { + throw exception(MD_WORKSTATION_NOT_EXISTS); + } + return workstation; + } + + private void validateWorkshopExists(Long workshopId) { + MesMdWorkshopDO workshop = workshopService.getWorkshop(workshopId); + if (workshop == null) { + throw exception(MD_WORKSHOP_NOT_EXISTS); + } + } + + /** + * 校验并处理仓库层级关系 + * + * 仓库层级结构:仓库 -> 库区 -> 库位 + * 处理规则: + * 1. 如果仓库/库区/库位都未填写,则自动设置虚拟线边库 + * 2. 如果填写了库区,必须填写仓库,且库区必须属于该仓库 + * 3. 如果填写了库位,必须填写库区,且库位必须属于该库区 + * + * @param reqVO 工作站保存请求对象 + */ + private void handleWarehouseHierarchy(MesMdWorkstationSaveReqVO reqVO) { + // 1.1 获取仓库、库区、库位 ID + Long warehouseId = reqVO.getWarehouseId(); + Long locationId = reqVO.getLocationId(); + Long areaId = reqVO.getAreaId(); + // 1.2 如果都为空,则自动设置虚拟线边库 + if (warehouseId == null && locationId == null && areaId == null) { + MesWmWarehouseDO warehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + MesWmWarehouseLocationDO location = locationService.getWarehouseLocationByCode( + MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + MesWmWarehouseAreaDO area = areaService.getWarehouseAreaByCode( + MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); + reqVO.setWarehouseId(warehouse.getId()); + reqVO.setLocationId(location.getId()); + reqVO.setAreaId(area.getId()); + return; + } + + // 2. 校验仓库是否存在 + if (warehouseId != null) { + warehouseService.validateWarehouseExists(warehouseId); + } + + // 3. 校验库区:如果填写了库区,必须填写仓库,且库区必须属于该仓库 + MesWmWarehouseLocationDO location; + if (locationId != null) { + // 3.1 校验库区是否存在 + location = locationService.validateWarehouseLocationExists(locationId); + // 3.2 校验必须填写仓库 + if (warehouseId == null) { + throw exception(WM_WAREHOUSE_REQUIRED); + } + // 3.3 校验库区是否属于该仓库 + if (ObjUtil.notEqual(location.getWarehouseId(), warehouseId)) { + throw exception(WM_WAREHOUSE_LOCATION_RELATION_INVALID); + } + } + + // 4. 校验库位:如果填写了库位,必须填写库区,且库位必须属于该库区 + if (areaId == null) { + return; + } + // 4.1 校验库位是否存在 + MesWmWarehouseAreaDO area = areaService.validateWarehouseAreaExists(areaId); + // 4.2 校验必须填写库区 + if (locationId == null) { + throw exception(WM_WAREHOUSE_LOCATION_REQUIRED); + } + // 4.3 校验库位是否属于该库区 + if (ObjUtil.notEqual(area.getLocationId(), locationId)) { + throw exception(WM_WAREHOUSE_AREA_RELATION_INVALID); + } + } + + private void validateWorkstationCodeUnique(Long id, String code) { + MesMdWorkstationDO workstation = workstationMapper.selectByCode(code); + if (workstation == null) { + return; + } + if (ObjUtil.notEqual(workstation.getId(), id)) { + throw exception(MD_WORKSTATION_CODE_DUPLICATE); + } + } + + private void validateWorkstationNameUnique(Long id, String name) { + MesMdWorkstationDO workstation = workstationMapper.selectByName(name); + if (workstation == null) { + return; + } + if (ObjUtil.notEqual(workstation.getId(), id)) { + throw exception(MD_WORKSTATION_NAME_DUPLICATE); + } + } + + @Override + public MesMdWorkstationDO getWorkstation(Long id) { + return workstationMapper.selectById(id); + } + + @Override + public PageResult getWorkstationPage(MesMdWorkstationPageReqVO pageReqVO) { + return workstationMapper.selectPage(pageReqVO); + } + + @Override + public List getWorkstationListByStatus(Integer status) { + return workstationMapper.selectListByStatus(status); + } + + @Override + public Long getWorkstationCountByWarehouseId(Long warehouseId) { + return workstationMapper.selectCountByWarehouseId(warehouseId); + } + + @Override + public Long getWorkstationCountByLocationId(Long locationId) { + return workstationMapper.selectCountByLocationId(locationId); + } + + @Override + public Long getWorkstationCountByAreaId(Long areaId) { + return workstationMapper.selectCountByAreaId(areaId); + } + + @Override + public List getWorkstationList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return workstationMapper.selectByIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolService.java new file mode 100644 index 000000000..bf5160d2e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolService.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.tool.MesMdWorkstationToolSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationToolDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 工装夹具资源 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdWorkstationToolService { + + /** + * 创建工装夹具资源 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkstationTool(@Valid MesMdWorkstationToolSaveReqVO createReqVO); + + /** + * 更新工装夹具资源 + * + * @param updateReqVO 更新信息 + */ + void updateWorkstationTool(@Valid MesMdWorkstationToolSaveReqVO updateReqVO); + + /** + * 删除工装夹具资源 + * + * @param id 编号 + */ + void deleteWorkstationTool(Long id); + + /** + * 获得工装夹具资源列表 + * + * @param workstationId 工作站编号 + * @return 工装夹具资源列表 + */ + List getWorkstationToolListByWorkstationId(Long workstationId); + + /** + * 按工作站编号删除工装夹具资源(级联删除) + * + * @param workstationId 工作站编号 + */ + void deleteWorkstationToolByWorkstationId(Long workstationId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolServiceImpl.java new file mode 100644 index 000000000..a8f5d51eb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolServiceImpl.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.tool.MesMdWorkstationToolSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationToolDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationToolMapper; +import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolTypeService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 工装夹具资源 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdWorkstationToolServiceImpl implements MesMdWorkstationToolService { + + @Resource + private MesMdWorkstationToolMapper workstationToolMapper; + + @Resource + private MesTmToolTypeService toolTypeService; + + @Override + public Long createWorkstationTool(MesMdWorkstationToolSaveReqVO createReqVO) { + // 校验数据 + validateWorkstationToolSaveData(null, createReqVO); + + // 插入 + MesMdWorkstationToolDO tool = BeanUtils.toBean(createReqVO, MesMdWorkstationToolDO.class); + workstationToolMapper.insert(tool); + return tool.getId(); + } + + @Override + public void updateWorkstationTool(MesMdWorkstationToolSaveReqVO updateReqVO) { + // 校验存在 + validateWorkstationToolExists(updateReqVO.getId()); + // 校验数据 + validateWorkstationToolSaveData(updateReqVO.getId(), updateReqVO); + + // 更新 + MesMdWorkstationToolDO updateObj = BeanUtils.toBean(updateReqVO, MesMdWorkstationToolDO.class); + workstationToolMapper.updateById(updateObj); + } + + private void validateWorkstationToolSaveData(Long id, MesMdWorkstationToolSaveReqVO reqVO) { + // 校验工具类型是否存在 + toolTypeService.validateToolTypeExists(reqVO.getToolTypeId()); + // 校验同一工作站下工具类型不重复(排除自身) + MesMdWorkstationToolDO existing = workstationToolMapper.selectByWorkstationIdAndToolTypeId( + reqVO.getWorkstationId(), reqVO.getToolTypeId()); + if (existing != null && ObjUtil.notEqual(existing.getId(), id)) { + throw exception(MD_WORKSTATION_TOOL_TYPE_EXISTS); + } + } + + @Override + public void deleteWorkstationTool(Long id) { + // 校验存在 + validateWorkstationToolExists(id); + + // 删除 + workstationToolMapper.deleteById(id); + } + + private void validateWorkstationToolExists(Long id) { + if (workstationToolMapper.selectById(id) == null) { + throw exception(MD_WORKSTATION_TOOL_NOT_EXISTS); + } + } + + @Override + public List getWorkstationToolListByWorkstationId(Long workstationId) { + return workstationToolMapper.selectListByWorkstationId(workstationId); + } + + @Override + public void deleteWorkstationToolByWorkstationId(Long workstationId) { + workstationToolMapper.deleteByWorkstationId(workstationId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationWorkerService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationWorkerService.java new file mode 100644 index 000000000..ce818fcbc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationWorkerService.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.worker.MesMdWorkstationWorkerSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationWorkerDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 人力资源 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdWorkstationWorkerService { + + /** + * 创建人力资源 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkstationWorker(@Valid MesMdWorkstationWorkerSaveReqVO createReqVO); + + /** + * 更新人力资源 + * + * @param updateReqVO 更新信息 + */ + void updateWorkstationWorker(@Valid MesMdWorkstationWorkerSaveReqVO updateReqVO); + + /** + * 删除人力资源 + * + * @param id 编号 + */ + void deleteWorkstationWorker(Long id); + + /** + * 获得人力资源列表 + * + * @param workstationId 工作站编号 + * @return 人力资源列表 + */ + List getWorkstationWorkerListByWorkstationId(Long workstationId); + + /** + * 按工作站编号删除人力资源(级联删除) + * + * @param workstationId 工作站编号 + */ + void deleteWorkstationWorkerByWorkstationId(Long workstationId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationWorkerServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationWorkerServiceImpl.java new file mode 100644 index 000000000..63911968a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationWorkerServiceImpl.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.service.md.workstation; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.worker.MesMdWorkstationWorkerSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationWorkerDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationWorkerMapper; +import cn.iocoder.yudao.module.system.api.dept.PostApi; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 人力资源 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdWorkstationWorkerServiceImpl implements MesMdWorkstationWorkerService { + + @Resource + private MesMdWorkstationWorkerMapper workstationWorkerMapper; + + @Resource + private PostApi postApi; + + @Override + public Long createWorkstationWorker(MesMdWorkstationWorkerSaveReqVO createReqVO) { + // 校验数据 + validateWorkstationWorkerSaveData(null, createReqVO); + + // 插入 + MesMdWorkstationWorkerDO worker = BeanUtils.toBean(createReqVO, MesMdWorkstationWorkerDO.class); + workstationWorkerMapper.insert(worker); + return worker.getId(); + } + + @Override + public void updateWorkstationWorker(MesMdWorkstationWorkerSaveReqVO updateReqVO) { + // 校验存在 + validateWorkstationWorkerExists(updateReqVO.getId()); + // 校验数据 + validateWorkstationWorkerSaveData(updateReqVO.getId(), updateReqVO); + + // 更新 + MesMdWorkstationWorkerDO updateObj = BeanUtils.toBean(updateReqVO, MesMdWorkstationWorkerDO.class); + workstationWorkerMapper.updateById(updateObj); + } + + private void validateWorkstationWorkerSaveData(Long id, MesMdWorkstationWorkerSaveReqVO reqVO) { + // 校验岗位是否存在 + postApi.validPostList(Collections.singleton(reqVO.getPostId())); + // 校验同一工作站下岗位不重复(排除自身) + MesMdWorkstationWorkerDO existing = workstationWorkerMapper.selectByWorkstationIdAndPostId( + reqVO.getWorkstationId(), reqVO.getPostId()); + if (existing != null && ObjUtil.notEqual(existing.getId(), id)) { + throw exception(MD_WORKSTATION_WORKER_POST_EXISTS); + } + } + + @Override + public void deleteWorkstationWorker(Long id) { + // 校验存在 + validateWorkstationWorkerExists(id); + + // 删除 + workstationWorkerMapper.deleteById(id); + } + + private void validateWorkstationWorkerExists(Long id) { + if (workstationWorkerMapper.selectById(id) == null) { + throw exception(MD_WORKSTATION_WORKER_NOT_EXISTS); + } + } + + @Override + public List getWorkstationWorkerListByWorkstationId(Long workstationId) { + return workstationWorkerMapper.selectListByWorkstationId(workstationId); + } + + @Override + public void deleteWorkstationWorkerByWorkstationId(Long workstationId) { + workstationWorkerMapper.deleteByWorkstationId(workstationId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonConfigService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonConfigService.java new file mode 100644 index 000000000..f1c190a72 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonConfigService.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.service.pro.andon; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config.MesProAndonConfigPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config.MesProAndonConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonConfigDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 安灯呼叫配置 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProAndonConfigService { + + /** + * 创建安灯呼叫配置 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createAndonConfig(@Valid MesProAndonConfigSaveReqVO createReqVO); + + /** + * 更新安灯呼叫配置 + * + * @param updateReqVO 更新信息 + */ + void updateAndonConfig(@Valid MesProAndonConfigSaveReqVO updateReqVO); + + /** + * 删除安灯呼叫配置 + * + * @param id 编号 + */ + void deleteAndonConfig(Long id); + + /** + * 校验安灯呼叫配置存在 + * + * @param id 编号 + * @return 安灯呼叫配置 + */ + MesProAndonConfigDO validateAndonConfigExists(Long id); + + /** + * 获得安灯呼叫配置 + * + * @param id 编号 + * @return 安灯呼叫配置 + */ + MesProAndonConfigDO getAndonConfig(Long id); + + /** + * 获得安灯呼叫配置分页 + * + * @param pageReqVO 分页查询 + * @return 安灯呼叫配置分页 + */ + PageResult getAndonConfigPage(MesProAndonConfigPageReqVO pageReqVO); + + /** + * 获得安灯呼叫配置列表 + * + * @return 安灯呼叫配置列表 + */ + List getAndonConfigList(); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonConfigServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonConfigServiceImpl.java new file mode 100644 index 000000000..e33c86efd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonConfigServiceImpl.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.module.mes.service.pro.andon; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config.MesProAndonConfigPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.config.MesProAndonConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonConfigDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.andon.MesProAndonConfigMapper; +import cn.iocoder.yudao.module.system.api.permission.RoleApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_ANDON_CONFIG_NOT_EXISTS; + +/** + * MES 安灯呼叫配置 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProAndonConfigServiceImpl implements MesProAndonConfigService { + + @Resource + private MesProAndonConfigMapper andonConfigMapper; + + @Resource + private AdminUserApi adminUserApi; + @Resource + private RoleApi roleApi; + + @Override + public Long createAndonConfig(MesProAndonConfigSaveReqVO createReqVO) { + // 1. 校验处置人/角色存在 + validateHandlerUserAndRole(createReqVO); + + // 2. 插入 + MesProAndonConfigDO config = BeanUtils.toBean(createReqVO, MesProAndonConfigDO.class); + andonConfigMapper.insert(config); + return config.getId(); + } + + @Override + public void updateAndonConfig(MesProAndonConfigSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateAndonConfigExists(updateReqVO.getId()); + // 1.2 校验处置人/角色存在 + validateHandlerUserAndRole(updateReqVO); + + // 2. 更新 + MesProAndonConfigDO updateObj = BeanUtils.toBean(updateReqVO, MesProAndonConfigDO.class); + andonConfigMapper.updateById(updateObj); + } + + @Override + public void deleteAndonConfig(Long id) { + // 校验存在 + validateAndonConfigExists(id); + + // 删除 + andonConfigMapper.deleteById(id); + } + + @Override + public MesProAndonConfigDO validateAndonConfigExists(Long id) { + MesProAndonConfigDO config = andonConfigMapper.selectById(id); + if (config == null) { + throw exception(PRO_ANDON_CONFIG_NOT_EXISTS); + } + return config; + } + + @Override + public MesProAndonConfigDO getAndonConfig(Long id) { + return andonConfigMapper.selectById(id); + } + + @Override + public PageResult getAndonConfigPage(MesProAndonConfigPageReqVO pageReqVO) { + return andonConfigMapper.selectPage(pageReqVO); + } + + @Override + public List getAndonConfigList() { + return andonConfigMapper.selectList(); + } + + // ==================== 校验方法 ==================== + + private void validateHandlerUserAndRole(MesProAndonConfigSaveReqVO reqVO) { + if (reqVO.getHandlerUserId() != null) { + adminUserApi.validateUser(reqVO.getHandlerUserId()); + } + if (reqVO.getHandlerRoleId() != null) { + roleApi.validRoleList(Collections.singleton(reqVO.getHandlerRoleId())); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordService.java new file mode 100644 index 000000000..3c39aec3e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.mes.service.pro.andon; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordUpdateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordCreateReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonRecordDO; +import jakarta.validation.Valid; + +/** + * MES 安灯呼叫记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProAndonRecordService { + + /** + * 创建安灯呼叫记录 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createAndonRecord(@Valid MesProAndonRecordCreateReqVO createReqVO); + + /** + * 删除安灯呼叫记录 + * + * @param id 编号 + */ + void deleteAndonRecord(Long id); + + /** + * 更新安灯呼叫记录(保存处置信息 / 标记已处置) + * + * @param updateReqVO 更新信息 + */ + void updateAndonRecord(@Valid MesProAndonRecordUpdateReqVO updateReqVO); + + /** + * 获得安灯呼叫记录 + * + * @param id 编号 + * @return 安灯呼叫记录 + */ + MesProAndonRecordDO getAndonRecord(Long id); + + /** + * 获得安灯呼叫记录分页 + * + * @param pageReqVO 分页查询 + * @return 安灯呼叫记录分页 + */ + PageResult getAndonRecordPage(MesProAndonRecordPageReqVO pageReqVO); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordServiceImpl.java new file mode 100644 index 000000000..db7e6add6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordServiceImpl.java @@ -0,0 +1,115 @@ +package cn.iocoder.yudao.module.mes.service.pro.andon; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordUpdateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record.MesProAndonRecordCreateReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonConfigDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.andon.MesProAndonRecordDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.andon.MesProAndonRecordMapper; +import cn.iocoder.yudao.module.mes.enums.pro.MesProAndonStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 安灯呼叫记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProAndonRecordServiceImpl implements MesProAndonRecordService { + + @Resource + private MesProAndonRecordMapper andonRecordMapper; + + @Resource + private MesMdWorkstationService workstationService; + + @Resource + private MesProWorkOrderService workOrderService; + + @Resource + private MesProProcessService processService; + + @Resource + private MesProAndonConfigService andonConfigService; + + @Override + public Long createAndonRecord(MesProAndonRecordCreateReqVO createReqVO) { + // 1. 校验关联数据存在 + MesProAndonConfigDO config = andonConfigService.validateAndonConfigExists(createReqVO.getConfigId()); + workstationService.validateWorkstationExists(createReqVO.getWorkstationId()); + if (createReqVO.getWorkOrderId() != null) { + workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); + } + if (createReqVO.getProcessId() != null) { + processService.validateProcessExists(createReqVO.getProcessId()); + } + + // 2. 插入记录 + MesProAndonRecordDO record = BeanUtils.toBean(createReqVO, MesProAndonRecordDO.class); + record.setReason(config.getReason()).setLevel(config.getLevel()); // 快照配置中的原因和级别 + record.setStatus(MesProAndonStatusEnum.ACTIVE.getStatus()); + andonRecordMapper.insert(record); + return record.getId(); + } + + @Override + public void deleteAndonRecord(Long id) { + // 1. 校验存在,且未处置 + validateAndonRecordNotHandled(id); + // 2. 删除 + andonRecordMapper.deleteById(id); + } + + @Override + public void updateAndonRecord(MesProAndonRecordUpdateReqVO updateReqVO) { + // 1. 校验存在,且未处置 + validateAndonRecordNotHandled(updateReqVO.getId()); + + // 2. 更新 + andonRecordMapper.updateById(new MesProAndonRecordDO().setId(updateReqVO.getId()) + .setStatus(updateReqVO.getStatus()) + .setHandleTime(updateReqVO.getHandleTime()) + .setHandlerUserId(updateReqVO.getHandlerUserId()) + .setRemark(updateReqVO.getRemark())); + } + + /** + * 校验安灯记录存在,且未处置 + * + * @param id 编号 + * @return 安灯记录 + */ + private MesProAndonRecordDO validateAndonRecordNotHandled(Long id) { + MesProAndonRecordDO record = andonRecordMapper.selectById(id); + if (record == null) { + throw exception(PRO_ANDON_RECORD_NOT_EXISTS); + } + if (ObjUtil.equal(record.getStatus(), MesProAndonStatusEnum.HANDLED.getStatus())) { + throw exception(PRO_ANDON_RECORD_ALREADY_HANDLED); + } + return record; + } + + @Override + public MesProAndonRecordDO getAndonRecord(Long id) { + return andonRecordMapper.selectById(id); + } + + @Override + public PageResult getAndonRecordPage(MesProAndonRecordPageReqVO pageReqVO) { + return andonRecordMapper.selectPage(pageReqVO); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessService.java new file mode 100644 index 000000000..db4245fcf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.service.pro.card; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process.MesProCardProcessPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process.MesProCardProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardProcessDO; +import jakarta.validation.Valid; + +/** + * MES 流转卡工序记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProCardProcessService { + + /** + * 创建流转卡工序记录 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCardProcess(@Valid MesProCardProcessSaveReqVO createReqVO); + + /** + * 更新流转卡工序记录 + * + * @param updateReqVO 更新信息 + */ + void updateCardProcess(@Valid MesProCardProcessSaveReqVO updateReqVO); + + /** + * 删除流转卡工序记录 + * + * @param id 编号 + */ + void deleteCardProcess(Long id); + + /** + * 获得流转卡工序记录 + * + * @param id 编号 + * @return 流转卡工序记录 + */ + MesProCardProcessDO getCardProcess(Long id); + + /** + * 获得流转卡工序记录分页 + * + * @param pageReqVO 分页查询 + * @return 流转卡工序记录分页 + */ + PageResult getCardProcessPage(MesProCardProcessPageReqVO pageReqVO); + + /** + * 根据流转卡编号,删除工序记录 + * + * @param cardId 流转卡编号 + */ + void deleteCardProcessByCardId(Long cardId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessServiceImpl.java new file mode 100644 index 000000000..5803bfda5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessServiceImpl.java @@ -0,0 +1,101 @@ +package cn.iocoder.yudao.module.mes.service.pro.card; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process.MesProCardProcessPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.process.MesProCardProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardProcessDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.card.MesProCardProcessMapper; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_CARD_PROCESS_NOT_EXISTS; + +/** + * MES 流转卡工序记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProCardProcessServiceImpl implements MesProCardProcessService { + + @Resource + private MesProCardProcessMapper cardProcessMapper; + + @Resource + @Lazy + private MesProCardService cardService; + + @Resource + private MesProProcessService processService; + + @Override + public Long createCardProcess(MesProCardProcessSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateCardProcessSaveData(createReqVO); + + // 2. 插入 + MesProCardProcessDO cardProcess = BeanUtils.toBean(createReqVO, MesProCardProcessDO.class); + cardProcessMapper.insert(cardProcess); + return cardProcess.getId(); + } + + @Override + public void updateCardProcess(MesProCardProcessSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateCardProcessExists(updateReqVO.getId()); + // 1.2 校验关联数据 + validateCardProcessSaveData(updateReqVO); + + // 2. 更新 + MesProCardProcessDO updateObj = BeanUtils.toBean(updateReqVO, MesProCardProcessDO.class); + cardProcessMapper.updateById(updateObj); + } + + @Override + public void deleteCardProcess(Long id) { + // 1. 校验存在 + validateCardProcessExists(id); + + // 2. 删除 + cardProcessMapper.deleteById(id); + } + + @Override + public MesProCardProcessDO getCardProcess(Long id) { + return cardProcessMapper.selectById(id); + } + + @Override + public PageResult getCardProcessPage(MesProCardProcessPageReqVO pageReqVO) { + return cardProcessMapper.selectPage(pageReqVO); + } + + // ==================== 校验方法 ==================== + + private void validateCardProcessExists(Long id) { + if (cardProcessMapper.selectById(id) == null) { + throw exception(PRO_CARD_PROCESS_NOT_EXISTS); + } + } + + private void validateCardProcessSaveData(MesProCardProcessSaveReqVO reqVO) { + // 校验流转卡存在 + cardService.validateCardExists(reqVO.getCardId()); + // 校验工序存在 + if (reqVO.getProcessId() != null) { + processService.validateProcessExists(reqVO.getProcessId()); + } + } + + @Override + public void deleteCardProcessByCardId(Long cardId) { + cardProcessMapper.deleteByCardId(cardId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardService.java new file mode 100644 index 000000000..a8af47cc3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardService.java @@ -0,0 +1,91 @@ +package cn.iocoder.yudao.module.mes.service.pro.card; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 生产流转卡 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProCardService { + + /** + * 创建生产流转卡 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCard(@Valid MesProCardSaveReqVO createReqVO); + + /** + * 更新生产流转卡 + * + * @param updateReqVO 更新信息 + */ + void updateCard(@Valid MesProCardSaveReqVO updateReqVO); + + /** + * 删除生产流转卡 + * + * @param id 编号 + */ + void deleteCard(Long id); + + /** + * 校验生产流转卡存在 + * + * @param id 编号 + */ + void validateCardExists(Long id); + + /** + * 获得生产流转卡 + * + * @param id 编号 + * @return 生产流转卡 + */ + MesProCardDO getCard(Long id); + + /** + * 获得生产流转卡分页 + * + * @param pageReqVO 分页查询 + * @return 生产流转卡分页 + */ + PageResult getCardPage(MesProCardPageReqVO pageReqVO); + + /** + * 获得生产流转卡精简列表 + * + * @return 流转卡列表 + */ + List getCardSimpleList(); + + /** + * 提交生产流转卡(草稿 → 已确认) + * + * @param id 编号 + */ + void submitCard(Long id); + + /** + * 完成生产流转卡(已确认 → 已完成) + * + * @param id 编号 + */ + void finishCard(Long id); + + /** + * 取消生产流转卡(任意非已完成/已取消状态 → 已取消) + * + * @param id 编号 + */ + void cancelCard(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java new file mode 100644 index 000000000..3be908bf7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java @@ -0,0 +1,186 @@ +package cn.iocoder.yudao.module.mes.service.pro.card; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.card.MesProCardMapper; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 生产流转卡 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProCardServiceImpl implements MesProCardService { + + @Resource + private MesProCardMapper cardMapper; + + // DONE @AI:会用对应的 service + @Resource + @Lazy + private MesProCardProcessService cardProcessService; + + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createCard(MesProCardSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateCardSaveData(createReqVO); + + // 2. 插入 + MesProCardDO card = BeanUtils.toBean(createReqVO, MesProCardDO.class) + .setStatus(MesProWorkOrderStatusEnum.PREPARE.getStatus()); + cardMapper.insert(card); + + // 3. 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.PROCARD.getValue(), + card.getId(), card.getCode(), card.getCode()); + return card.getId(); + } + + @Override + public void updateCard(MesProCardSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateCardExists(updateReqVO.getId()); + // 1.2 校验关联数据 + validateCardSaveData(updateReqVO); + + // 2. 更新 + MesProCardDO updateObj = BeanUtils.toBean(updateReqVO, MesProCardDO.class); + cardMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteCard(Long id) { + // 1. 校验存在 + validateCardExists(id); + + // 2. 删除流转卡 + 级联删除工序记录 + cardMapper.deleteById(id); + cardProcessService.deleteCardProcessByCardId(id); + } + + @Override + public MesProCardDO getCard(Long id) { + return cardMapper.selectById(id); + } + + @Override + public PageResult getCardPage(MesProCardPageReqVO pageReqVO) { + return cardMapper.selectPage(pageReqVO); + } + + @Override + public List getCardSimpleList() { + return cardMapper.selectList(); + } + + @Override + public void submitCard(Long id) { + // 1. 校验存在 + 草稿状态 + validateCardExistsAndStatus(id, MesProWorkOrderStatusEnum.PREPARE); + + // 2. 提交(草稿 → 已确认) + cardMapper.updateById(new MesProCardDO() + .setId(id).setStatus(MesProWorkOrderStatusEnum.CONFIRMED.getStatus())); + } + + @Override + public void finishCard(Long id) { + // 1. 校验存在 + 已确认状态 + validateCardExistsAndStatus(id, MesProWorkOrderStatusEnum.CONFIRMED); + + // 2. 完成(已确认 → 已完成) + cardMapper.updateById(new MesProCardDO() + .setId(id).setStatus(MesProWorkOrderStatusEnum.FINISHED.getStatus())); + } + + @Override + public void cancelCard(Long id) { + // 1.1 校验存在 + MesProCardDO card = validateCardExistsInternal(id); + // 1.2 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(card.getStatus(), + MesProWorkOrderStatusEnum.FINISHED.getStatus(), + MesProWorkOrderStatusEnum.CANCELED.getStatus())) { + throw exception(PRO_CARD_CANCEL_NOT_ALLOWED); + } + + // 2. 取消 + cardMapper.updateById(new MesProCardDO() + .setId(id).setStatus(MesProWorkOrderStatusEnum.CANCELED.getStatus())); + } + + // ==================== 校验方法 ==================== + + @Override + public void validateCardExists(Long id) { + validateCardExistsInternal(id); + } + + private MesProCardDO validateCardExistsInternal(Long id) { + MesProCardDO card = cardMapper.selectById(id); + if (card == null) { + throw exception(PRO_CARD_NOT_EXISTS); + } + return card; + } + + private MesProCardDO validateCardExistsAndStatus(Long id, MesProWorkOrderStatusEnum status) { + MesProCardDO card = validateCardExistsInternal(id); + if (ObjUtil.notEqual(status.getStatus(), card.getStatus())) { + throw exception(PRO_CARD_STATUS_ERROR); + } + return card; + } + + private void validateCardCodeUnique(Long id, String code) { + if (code == null) { + return; + } + MesProCardDO card = cardMapper.selectByCode(code); + if (card == null) { + return; + } + if (ObjUtil.notEqual(card.getId(), id)) { + throw exception(PRO_CARD_CODE_DUPLICATE); + } + } + + private void validateCardSaveData(MesProCardSaveReqVO reqVO) { + // 校验编码唯一 + validateCardCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验工单存在 + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java new file mode 100644 index 000000000..2729b1059 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.mes.service.pro.feedback; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; + +/** + * MES 生产报工 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProFeedbackService { + + /** + * 创建生产报工(草稿) + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createFeedback(@Valid MesProFeedbackSaveReqVO createReqVO); + + /** + * 修改生产报工 + * + * @param updateReqVO 更新信息 + */ + void updateFeedback(@Valid MesProFeedbackSaveReqVO updateReqVO); + + /** + * 删除生产报工(仅草稿) + * + * @param id 编号 + */ + void deleteFeedback(Long id); + + /** + * 获得生产报工 + * + * @param id 编号 + * @return 生产报工 + */ + MesProFeedbackDO getFeedback(Long id); + + /** + * 获得生产报工分页 + * + * @param pageReqVO 分页查询 + * @return 生产报工分页 + */ + PageResult getFeedbackPage(MesProFeedbackPageReqVO pageReqVO); + + /** + * 提交报工(草稿 → 审批中) + * + * @param id 编号 + */ + void submitFeedback(Long id); + + /** + * 驳回报工(审批中 → 草稿) + * + * @param id 编号 + */ + void rejectFeedback(Long id); + + /** + * 审批通过报工单,执行生产入库流程 + * + *

整体流程如下: + *

    + *
  1. 校验报工单状态和数量
  2. + *
  3. 生成物料消耗单,扣减线边库物料
  4. + *
  5. 根据工序配置(关键工序 & 是否需要检验)分情况处理: + *
      + *
    • 关键工序 + 需要检验:生成产出单(质量状态=待检验),报工单状态 → 待检验,等待质检完成回调
    • + *
    • 关键工序 + 无需检验:生成产出单(按合格/不合格拆行),执行产品入库,更新任务/工单已生产数量,报工单状态 → 已完成
    • + *
    • 非关键工序:不生成产出单,不更新任务/工单数量,报工单状态 → 已完成
    • + *
    + *
  6. + *
+ * + * @param id 报工单编号 + * @param userId 当前操作用户编号(审核人) + * @return true=已完成, false=待检验(需等质检回调) + */ + boolean approveFeedback(Long id, Long userId); + + /** + * IPQC 完成后回调:完成报工单并更新任务/工单进度 + * + *

由 IPQC 检验完成时调用,将报工单状态从待检验改为已完成, + * 并根据检验结果回写合格/不合格/废品数量,同时更新任务/工单的已生产数量。 + * + * @param feedbackId 报工记录 ID + * @param qualifiedQty 合格品数量 + * @param unqualifiedQty 不合格品数量 + * @param laborScrapQty 工废数量 + * @param materialScrapQty 料废数量 + * @param otherScrapQty 其他废品数量 + */ + void updateProFeedbackWhenIpqcFinish(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty, + BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty); + +} + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java new file mode 100644 index 000000000..b631427d8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java @@ -0,0 +1,314 @@ +package cn.iocoder.yudao.module.mes.service.pro.feedback; + +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; +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.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +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.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.itemconsume.MesWmItemConsumeService; +import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService; +import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 生产报工 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProFeedbackServiceImpl implements MesProFeedbackService { + + @Resource + private MesProFeedbackMapper feedbackMapper; + + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesProRouteProcessService routeProcessService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + @Lazy // 避免循环依赖 + private MesProTaskService taskService; + @Resource + private MesWmItemConsumeService itemConsumeService; + @Resource + private MesWmProductProduceService productProduceService; + @Resource + private MesWmProductProduceLineService produceLineService; + + @Override + public Long createFeedback(MesProFeedbackSaveReqVO createReqVO) { + // 1. 校验 + MesProTaskDO task = validateFeedbackData(createReqVO); + + // 2. 插入(自动填充 itemId) + MesProFeedbackDO feedback = BeanUtils.toBean(createReqVO, MesProFeedbackDO.class) + .setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus()) + .setItemId(task.getItemId()); + feedbackMapper.insert(feedback); + return feedback.getId(); + } + + @Override + public void updateFeedback(MesProFeedbackSaveReqVO updateReqVO) { + // 1.1 校验存在 + 草稿状态 + validateFeedbackStatusPrepare(updateReqVO.getId()); + // 1.2 校验业务数据 + MesProTaskDO task = validateFeedbackData(updateReqVO); + + // 2. 更新(自动填充 itemId) + MesProFeedbackDO updateObj = BeanUtils.toBean(updateReqVO, MesProFeedbackDO.class) + .setItemId(task.getItemId()); + feedbackMapper.updateById(updateObj); + } + + @Override + public void deleteFeedback(Long id) { + // 1. 校验存在 + 草稿状态 + validateFeedbackStatusPrepare(id); + + // 2. 删除 + feedbackMapper.deleteById(id); + } + + @Override + public MesProFeedbackDO getFeedback(Long id) { + return feedbackMapper.selectById(id); + } + + @Override + public PageResult getFeedbackPage(MesProFeedbackPageReqVO pageReqVO) { + return feedbackMapper.selectPage(pageReqVO); + } + + @Override + public void submitFeedback(Long id) { + // 1. 校验存在 + 草稿状态 + validateFeedbackStatusPrepare(id); + + // 2. 更新状态为审批中,记录报工人和报工时间 + feedbackMapper.updateById(new MesProFeedbackDO().setId(id) + .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()) + .setFeedbackUserId(getLoginUserId()) + .setFeedbackTime(LocalDateTime.now())); + } + + @Override + public void rejectFeedback(Long id) { + // 1. 校验存在 + 审批中状态 + validateFeedbackStatusApproving(id); + + // 2. 更新状态为草稿 + feedbackMapper.updateById(new MesProFeedbackDO().setId(id) + .setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean approveFeedback(Long id, Long userId) { + // 1.1.a 校验存在 + 审批中状态 + MesProFeedbackDO feedback = validateFeedbackStatusApproving(id); + // 1.1.b 校验报工数量 > 0 + if (feedback.getFeedbackQuantity() == null + || feedback.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) { + throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE); + } + // 1.2.a 校验任务未完成 + taskService.validateTaskNotFinished(feedback.getTaskId()); + // 1.2.b 仍有待检数量时不能执行 + if (feedback.getUncheckQuantity() != null + && feedback.getUncheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PRO_FEEDBACK_UNCHECK_QUANTITY_EXISTS, feedback.getUncheckQuantity()); + } + + // 2. 物料消耗:根据工序 BOM 生成消耗记录并执行扣减 + MesWmItemConsumeDO itemConsume = itemConsumeService.generateItemConsume(feedback); + if (itemConsume != null) { + itemConsumeService.finishItemConsume(itemConsume.getId()); + } + + // 3. 查询工序的关键工序标识 + 检验标识 + MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId( + feedback.getRouteId(), feedback.getProcessId()); + boolean keyFlag = routeProcess != null && Boolean.TRUE.equals(routeProcess.getKeyFlag()); + boolean checkFlag = routeProcess != null && Boolean.TRUE.equals(routeProcess.getCheckFlag()); + + // 4. 关键工序:生成产出单,并根据是否需要检验决定入库方式 + if (keyFlag) { + // 4.1 需要检验:生成产出单(质量状态=待检验),更新报工状态为待检验,等质检完成回调后再入库 + if (checkFlag) { + // 完成时回调见:MesQcIpqcServiceImpl#finishIpqc → splitPendingAndFinishProduce + completeFeedbackFromIpqc + productProduceService.generateProductProduce(feedback, true); + feedbackMapper.updateById(new MesProFeedbackDO().setId(id) + .setStatus(MesProFeedbackStatusEnum.UNCHECK.getStatus())); + return false; + } + // 4.2 无需检验:生成产出单(按合格/不合格拆行),直接完成入库,并更新任务/工单的已生产数量 + MesWmProductProduceDO produce = productProduceService.generateProductProduce(feedback, false); + productProduceService.finishProductProduce(produce.getId()); + updateTaskAndWorkOrderByFeedback(feedback); + } + + // 5. 非关键工序:不生成产出单,不更新任务/工单数量,直接完成 + feedbackMapper.updateById(new MesProFeedbackDO().setId(id) + .setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus()) + .setApproveUserId(userId)); + return true; // 已完成 + } + + /** + * 根据当前报工单的最终结果,更新生产任务和生产工单的进度 + * + *

    + *
  • 使用报工数量(feedbackQuantity),累加任务和工单的已生产数量
  • + *
  • 使用产出单行按 qualityStatus 聚合的合格品/不合格品数量,累加任务的合格品/不合格品数量 + * (不直接用 feedback 上的数量,确保质检回调场景下数量来源正确)
  • + *
+ * + * @param feedback 报工单 + */ + private void updateTaskAndWorkOrderByFeedback(MesProFeedbackDO feedback) { + // 1. 查询该报工单关联的所有产出单行,按质量状态聚合数量 + BigDecimal qualifiedQty = BigDecimal.ZERO; + BigDecimal unqualifiedQty = BigDecimal.ZERO; + List lines = produceLineService.getProductProduceLineListByFeedbackId(feedback.getId()); + for (MesWmProductProduceLineDO line : lines) { + if (ObjUtil.equal(line.getQualityStatus(), MesWmQualityStatusEnum.FAIL.getStatus())) { + unqualifiedQty = unqualifiedQty.add(line.getQuantity()); + } + if (ObjUtil.equal(line.getQualityStatus(), MesWmQualityStatusEnum.PASS.getStatus())) { + qualifiedQty = qualifiedQty.add(line.getQuantity()); + } + } + + // 2. 更新任务的已生产/合格/不合格数量 + taskService.updateProducedQuantity(feedback.getTaskId(), + feedback.getFeedbackQuantity(), qualifiedQty, unqualifiedQty); + // 3. 更新工单的已生产数量 + workOrderService.updateProducedQuantity(feedback.getWorkOrderId(), + feedback.getFeedbackQuantity()); + } + + // ==================== 校验方法 ==================== + + private MesProFeedbackDO validateFeedbackExists(Long id) { + MesProFeedbackDO feedback = feedbackMapper.selectById(id); + if (feedback == null) { + throw exception(PRO_FEEDBACK_NOT_EXISTS); + } + return feedback; + } + + private MesProFeedbackDO validateFeedbackStatusPrepare(Long id) { + MesProFeedbackDO feedback = validateFeedbackExists(id); + if (ObjUtil.notEqual(feedback.getStatus(), MesProFeedbackStatusEnum.PREPARE.getStatus())) { + throw exception(PRO_FEEDBACK_NOT_PREPARE); + } + return feedback; + } + + private MesProFeedbackDO validateFeedbackStatusApproving(Long id) { + MesProFeedbackDO feedback = validateFeedbackExists(id); + if (ObjUtil.notEqual(feedback.getStatus(), MesProFeedbackStatusEnum.APPROVING.getStatus())) { + throw exception(PRO_FEEDBACK_NOT_APPROVING); + } + return feedback; + } + + /** + * 校验报工单的业务数据(创建 & 修改共用) + * + * @param reqVO 报工请求 + * @return 关联的生产任务 + */ + private MesProTaskDO validateFeedbackData(MesProFeedbackSaveReqVO reqVO) { + // 1. 校验工作站存在 + workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + + // 2.1 校验工艺路线 + 工序配置有效 + MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId( + reqVO.getRouteId(), reqVO.getProcessId()); + if (routeProcess == null) { + throw exception(PRO_FEEDBACK_ROUTE_PROCESS_INVALID); + } + // 2.2 校验数量 + boolean checkFlag = Boolean.TRUE.equals(routeProcess.getCheckFlag()); + if (checkFlag) { + // 需要检验:只需填报工数量,且必须 > 0 + if (reqVO.getFeedbackQuantity() == null + || reqVO.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) { + throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE); + } + } else { + // 不需检验:需填合格品 + 不良品数量,合计 > 0 + BigDecimal qualified = ObjectUtil.defaultIfNull(reqVO.getQualifiedQuantity(), BigDecimal.ZERO); + BigDecimal unqualified = ObjectUtil.defaultIfNull(reqVO.getUnqualifiedQuantity(), BigDecimal.ZERO); + if (qualified.add(unqualified).compareTo(BigDecimal.ZERO) <= 0) { + throw exception(PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_REQUIRED); + } + } + + // 3. 校验工单已确认 + workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); + + // 4. 校验任务存在且未终态(已完成/已取消),并返回任务用于冗余 itemId + return taskService.validateTaskNotFinished(reqVO.getTaskId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateProFeedbackWhenIpqcFinish(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty, + BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty) { + // 1. 校验报工单存在且为待检验状态 + MesProFeedbackDO feedback = validateFeedbackExists(feedbackId); + if (ObjUtil.notEqual(feedback.getStatus(), MesProFeedbackStatusEnum.UNCHECK.getStatus())) { + throw exception(PRO_FEEDBACK_NOT_UNCHECK); + } + + // 2. 拆分待检产出行(合格/不合格),生成明细,完成产出入库 + productProduceService.splitPendingAndFinishProduce(feedbackId, qualifiedQty, unqualifiedQty); + + // 3. 回写合格/不合格/废品数量,更新状态为已完成 + feedbackMapper.updateById(new MesProFeedbackDO().setId(feedbackId) + .setQualifiedQuantity(qualifiedQty) + .setUnqualifiedQuantity(unqualifiedQty) + .setUncheckQuantity(BigDecimal.ZERO) + .setLaborScrapQuantity(laborScrapQty) + .setMaterialScrapQuantity(materialScrapQty) + .setOtherScrapQuantity(otherScrapQty) + .setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus())); + + // 4. 更新任务/工单的已生产数量 + feedback.setQualifiedQuantity(qualifiedQty).setUnqualifiedQuantity(unqualifiedQty); + updateTaskAndWorkOrderByFeedback(feedback); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessContentService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessContentService.java new file mode 100644 index 000000000..f558598ad --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessContentService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.service.pro.process; + +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.content.MesProProcessContentSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessContentDO; + +import jakarta.validation.Valid; +import java.util.List; + +/** + * MES 生产工序内容 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProProcessContentService { + + /** + * 创建生产工序内容 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProcessContent(@Valid MesProProcessContentSaveReqVO createReqVO); + + /** + * 更新生产工序内容 + * + * @param updateReqVO 更新信息 + */ + void updateProcessContent(@Valid MesProProcessContentSaveReqVO updateReqVO); + + /** + * 删除生产工序内容 + * + * @param id 编号 + */ + void deleteProcessContent(Long id); + + /** + * 获得生产工序内容 + * + * @param id 编号 + * @return 生产工序内容 + */ + MesProProcessContentDO getProcessContent(Long id); + + /** + * 获得生产工序内容列表(按工序编号) + * + * @param processId 工序编号 + * @return 生产工序内容列表 + */ + List getProcessContentListByProcessId(Long processId); + + /** + * 删除生产工序内容(按工序编号) + * + * @param processId 工序编号 + */ + void deleteProcessContentByProcessId(Long processId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessContentServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessContentServiceImpl.java new file mode 100644 index 000000000..8b1cedea5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessContentServiceImpl.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.service.pro.process; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.content.MesProProcessContentSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessContentDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.process.MesProProcessContentMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_PROCESS_CONTENT_NOT_EXISTS; + +/** + * MES 生产工序内容 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProProcessContentServiceImpl implements MesProProcessContentService { + + @Resource + private MesProProcessContentMapper processContentMapper; + + @Resource + @Lazy + private MesProProcessService processService; + + @Override + public Long createProcessContent(MesProProcessContentSaveReqVO createReqVO) { + // 校验工序存在 + processService.validateProcessExists(createReqVO.getProcessId()); + + // 插入 + MesProProcessContentDO content = BeanUtils.toBean(createReqVO, MesProProcessContentDO.class); + processContentMapper.insert(content); + return content.getId(); + } + + @Override + public void updateProcessContent(MesProProcessContentSaveReqVO updateReqVO) { + // 校验存在 + validateProcessContentExists(updateReqVO.getId()); + + // 更新 + MesProProcessContentDO updateObj = BeanUtils.toBean(updateReqVO, MesProProcessContentDO.class); + processContentMapper.updateById(updateObj); + } + + @Override + public void deleteProcessContent(Long id) { + // 校验存在 + validateProcessContentExists(id); + + // 删除 + processContentMapper.deleteById(id); + } + + private void validateProcessContentExists(Long id) { + if (processContentMapper.selectById(id) == null) { + throw exception(PRO_PROCESS_CONTENT_NOT_EXISTS); + } + } + + @Override + public MesProProcessContentDO getProcessContent(Long id) { + return processContentMapper.selectById(id); + } + + @Override + public List getProcessContentListByProcessId(Long processId) { + return processContentMapper.selectListByProcessId(processId); + } + + @Override + public void deleteProcessContentByProcessId(Long processId) { + processContentMapper.deleteByProcessId(processId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessService.java new file mode 100644 index 000000000..7d7c9b392 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessService.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.mes.service.pro.process; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcessPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; + +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 生产工序 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProProcessService { + + /** + * 创建生产工序 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProcess(@Valid MesProProcessSaveReqVO createReqVO); + + /** + * 更新生产工序 + * + * @param updateReqVO 更新信息 + */ + void updateProcess(@Valid MesProProcessSaveReqVO updateReqVO); + + /** + * 删除生产工序 + * + * @param id 编号 + */ + void deleteProcess(Long id); + + /** + * 获得生产工序 + * + * @param id 编号 + * @return 生产工序 + */ + MesProProcessDO getProcess(Long id); + + /** + * 获得生产工序列表 + * + * @param ids 编号列表 + * @return 生产工序列表 + */ + List getProcessList(Collection ids); + + /** + * 获得生产工序分页 + * + * @param pageReqVO 分页查询 + * @return 生产工序分页 + */ + PageResult getProcessPage(MesProProcessPageReqVO pageReqVO); + + /** + * 获得指定状态的生产工序列表 + * + * @param status 状态 + * @return 生产工序列表 + */ + List getProcessListByStatus(Integer status); + + /** + * 校验工序存在 + * + * @param id 编号 + */ + void validateProcessExists(Long id); + + /** + * 获得工序 Map + * + * @param ids 编号列表 + * @return 工序 Map + */ + default Map getProcessMap(Collection ids) { + return convertMap(getProcessList(ids), MesProProcessDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java new file mode 100644 index 000000000..838d4b4eb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.mes.service.pro.process; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcessPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.process.MesProProcessMapper; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 生产工序 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProProcessServiceImpl implements MesProProcessService { + + @Resource + private MesProProcessMapper processMapper; + + @Resource + private MesProProcessContentService processContentService; + + @Resource + @Lazy + private MesProRouteProcessService routeProcessService; + + @Override + public Long createProcess(MesProProcessSaveReqVO createReqVO) { + // 1. 校验编码、名称唯一 + validateProcessSaveData(createReqVO); + + // 2. 插入工序 + MesProProcessDO process = BeanUtils.toBean(createReqVO, MesProProcessDO.class); + processMapper.insert(process); + return process.getId(); + } + + @Override + public void updateProcess(MesProProcessSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateProcessExists(updateReqVO.getId()); + // 1.2 校验编码、名称唯一 + validateProcessSaveData(updateReqVO); + + // 2. 更新工序 + MesProProcessDO updateObj = BeanUtils.toBean(updateReqVO, MesProProcessDO.class); + processMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteProcess(Long id) { + // 1.1 校验存在 + validateProcessExists(id); + // 1.2 校验是否被工艺路线引用 + if (CollUtil.isNotEmpty(routeProcessService.getRouteProcessListByProcessId(id))) { + throw exception(PRO_PROCESS_USED_BY_ROUTE); + } + + // 2. 删除工序 + processMapper.deleteById(id); + // 3. 级联删除工序内容 + processContentService.deleteProcessContentByProcessId(id); + } + + @Override + public void validateProcessExists(Long id) { + if (processMapper.selectById(id) == null) { + throw exception(PRO_PROCESS_NOT_EXISTS); + } + } + + private void validateProcessCodeUnique(Long id, String code) { + MesProProcessDO process = processMapper.selectByCode(code); + if (process == null) { + return; + } + if (id == null) { + throw exception(PRO_PROCESS_CODE_EXISTS); + } + if (!process.getId().equals(id)) { + throw exception(PRO_PROCESS_CODE_EXISTS); + } + } + + private void validateProcessNameUnique(Long id, String name) { + MesProProcessDO process = processMapper.selectByName(name); + if (process == null) { + return; + } + if (id == null) { + throw exception(PRO_PROCESS_NAME_EXISTS); + } + if (!process.getId().equals(id)) { + throw exception(PRO_PROCESS_NAME_EXISTS); + } + } + + private void validateProcessSaveData(MesProProcessSaveReqVO saveReqVO) { + // 1. 校验编码唯一 + validateProcessCodeUnique(saveReqVO.getId(), saveReqVO.getCode()); + // 2. 校验名称唯一 + validateProcessNameUnique(saveReqVO.getId(), saveReqVO.getName()); + } + + @Override + public MesProProcessDO getProcess(Long id) { + return processMapper.selectById(id); + } + + @Override + public List getProcessList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return processMapper.selectByIds(ids); + } + + @Override + public PageResult getProcessPage(MesProProcessPageReqVO pageReqVO) { + return processMapper.selectPage(pageReqVO); + } + + @Override + public List getProcessListByStatus(Integer status) { + return processMapper.selectListByStatus(status); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessService.java new file mode 100644 index 000000000..96ccdabae --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.mes.service.pro.route; + +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProRouteProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * MES 工艺路线工序 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProRouteProcessService { + + /** + * 创建工艺路线工序 + */ + Long createRouteProcess(@Valid MesProRouteProcessSaveReqVO createReqVO); + + /** + * 更新工艺路线工序 + */ + void updateRouteProcess(@Valid MesProRouteProcessSaveReqVO updateReqVO); + + /** + * 删除工艺路线工序 + */ + void deleteRouteProcess(Long id); + + /** + * 获得工艺路线工序 + */ + MesProRouteProcessDO getRouteProcess(Long id); + + /** + * 按工艺路线获得工序列表 + */ + List getRouteProcessListByRouteId(Long routeId); + + /** + * 按多个工艺路线获得工序列表 + * + * @param routeIds 工艺路线编号数组 + * @return 工序列表 + */ + List getRouteProcessListByRouteIds(Collection routeIds); + + /** + * 按工艺路线和工序获得工艺路线工序 + * + * @param routeId 工艺路线编号 + * @param processId 工序编号 + * @return 工艺路线工序 + */ + MesProRouteProcessDO getRouteProcessByRouteIdAndProcessId(Long routeId, Long processId); + + /** + * 按产品获得工序列表 + * + * 根据产品查找关联的工艺路线,返回该路线的工序列表 + * + * @param productId 产品编号 + * @return 工序列表 + */ + List getRouteProcessListByProductId(Long productId); + + /** + * 按工序获得工艺路线工序列表 + * + * @param processId 工序编号 + * @return 工艺路线工序列表 + */ + List getRouteProcessListByProcessId(Long processId); + + /** + * 按工艺路线删除工序(级联删除使用) + * + * @param routeId 工艺路线编号 + */ + void deleteRouteProcessByRouteId(Long routeId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessServiceImpl.java new file mode 100644 index 000000000..20fca3e98 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessServiceImpl.java @@ -0,0 +1,212 @@ +package cn.iocoder.yudao.module.mes.service.pro.route; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProRouteProcessSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteProcessMapper; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 工艺路线工序 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProRouteProcessServiceImpl implements MesProRouteProcessService { + + @Resource + private MesProRouteProcessMapper routeProcessMapper; + + @Resource + @Lazy + private MesProRouteProductService routeProductService; + @Resource + @Lazy + private MesProProcessService processService; + @Resource + @Lazy + private MesProRouteService routeService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createRouteProcess(MesProRouteProcessSaveReqVO createReqVO) { + // 1.0 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(createReqVO.getRouteId()); + // 1.1 校验工艺路线、工序存在 + validateRouteAndProcessExists(createReqVO.getRouteId(), createReqVO.getProcessId()); + // 1.2 校验唯一性 + validateSortUnique(null, createReqVO.getRouteId(), createReqVO.getSort()); + validateProcessUnique(null, createReqVO.getRouteId(), createReqVO.getProcessId()); + validateKeyProcessUnique(null, createReqVO.getRouteId(), createReqVO.getKeyFlag()); + + // 2. 插入 + MesProRouteProcessDO routeProcess = BeanUtils.toBean(createReqVO, MesProRouteProcessDO.class); + routeProcessMapper.insert(routeProcess); + + // 3. 更新工序链 + rebuildProcessChain(createReqVO.getRouteId()); + return routeProcess.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateRouteProcess(MesProRouteProcessSaveReqVO updateReqVO) { + // 1.0 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(updateReqVO.getRouteId()); + // 1.1 校验存在 + validateRouteProcessExists(updateReqVO.getId()); + // 1.2 校验工艺路线、工序存在 + validateRouteAndProcessExists(updateReqVO.getRouteId(), updateReqVO.getProcessId()); + // 1.3 校验唯一性 + validateSortUnique(updateReqVO.getId(), updateReqVO.getRouteId(), updateReqVO.getSort()); + validateProcessUnique(updateReqVO.getId(), updateReqVO.getRouteId(), updateReqVO.getProcessId()); + validateKeyProcessUnique(updateReqVO.getId(), updateReqVO.getRouteId(), updateReqVO.getKeyFlag()); + + // 2. 更新 + MesProRouteProcessDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteProcessDO.class); + routeProcessMapper.updateById(updateObj); + + // 3. 重建工序链 + rebuildProcessChain(updateReqVO.getRouteId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteRouteProcess(Long id) { + // 1.1 校验存在 + MesProRouteProcessDO routeProcess = validateRouteProcessExists(id); + // 1.2 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(routeProcess.getRouteId()); + + // 2. 删除 + routeProcessMapper.deleteById(id); + + // 3. 重建工序链 + rebuildProcessChain(routeProcess.getRouteId()); + } + + /** + * 重建工序链(更新所有工序的 nextProcessId) + */ + private void rebuildProcessChain(Long routeId) { + List list = routeProcessMapper.selectListByRouteId(routeId); + if (CollUtil.isEmpty(list)) { + return; + } + // 按 sort 排序 + list.sort(Comparator.comparing(MesProRouteProcessDO::getSort)); + for (int i = 0; i < list.size(); i++) { + MesProRouteProcessDO item = list.get(i); + if (i + 1 < list.size()) { + item.setNextProcessId(list.get(i + 1).getProcessId()); + } else { + item.setNextProcessId(null); + } + routeProcessMapper.updateById(item); + } + } + + private MesProRouteProcessDO validateRouteProcessExists(Long id) { + MesProRouteProcessDO routeProcess = routeProcessMapper.selectById(id); + if (routeProcess == null) { + throw exception(PRO_ROUTE_PROCESS_NOT_EXISTS); + } + return routeProcess; + } + + private void validateRouteAndProcessExists(Long routeId, Long processId) { + if (routeService.getRoute(routeId) == null) { + throw exception(PRO_ROUTE_NOT_EXISTS); + } + if (processService.getProcess(processId) == null) { + throw exception(PRO_ROUTE_PROCESS_NOT_EXISTS); + } + } + + private void validateSortUnique(Long id, Long routeId, Integer sort) { + MesProRouteProcessDO existing = routeProcessMapper.selectByRouteIdAndSort(routeId, sort); + if (existing != null && !existing.getId().equals(id)) { + throw exception(PRO_ROUTE_PROCESS_SORT_DUPLICATE); + } + } + + private void validateProcessUnique(Long id, Long routeId, Long processId) { + MesProRouteProcessDO existing = routeProcessMapper.selectByRouteIdAndProcessId(routeId, processId); + if (existing != null && !existing.getId().equals(id)) { + throw exception(PRO_ROUTE_PROCESS_DUPLICATE); + } + } + + private void validateKeyProcessUnique(Long id, Long routeId, Boolean keyFlag) { + if (!Boolean.TRUE.equals(keyFlag)) { + return; + } + MesProRouteProcessDO existing = routeProcessMapper.selectKeyProcessByRouteId(routeId); + if (existing != null && !existing.getId().equals(id)) { + throw exception(PRO_ROUTE_PROCESS_KEY_DUPLICATE); + } + } + + @Override + public MesProRouteProcessDO getRouteProcess(Long id) { + return routeProcessMapper.selectById(id); + } + + @Override + public List getRouteProcessListByRouteId(Long routeId) { + return routeProcessMapper.selectListByRouteId(routeId); + } + + @Override + public List getRouteProcessListByRouteIds(Collection routeIds) { + if (CollUtil.isEmpty(routeIds)) { + return Collections.emptyList(); + } + return routeProcessMapper.selectListByRouteIds(routeIds); + } + + @Override + public MesProRouteProcessDO getRouteProcessByRouteIdAndProcessId(Long routeId, Long processId) { + return routeProcessMapper.selectByRouteIdAndProcessId(routeId, processId); + } + + @Override + public List getRouteProcessListByProductId(Long productId) { + // 1. 根据产品查找关联的工艺路线产品记录 + MesProRouteProductDO routeProduct = routeProductService.getRouteProductByItemId(productId); + if (routeProduct == null) { + // TODO @芋艿:会不会存在配置了多个的情况??? + // TODO @AI:会有这个情况么? + return Collections.emptyList(); + } + // 2. 返回该工艺路线的工序列表 + return routeProcessMapper.selectListByRouteId(routeProduct.getRouteId()); + } + + @Override + public List getRouteProcessListByProcessId(Long processId) { + return routeProcessMapper.selectListByProcessId(processId); + } + + @Override + public void deleteRouteProcessByRouteId(Long routeId) { + routeProcessMapper.deleteByRouteId(routeId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomService.java new file mode 100644 index 000000000..d2781fd14 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomService.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.service.pro.route; + +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 工艺路线产品 BOM Service 接口 + * + * @author 芋道源码 + */ +public interface MesProRouteProductBomService { + + /** + * 创建工艺路线产品 BOM + */ + Long createRouteProductBom(@Valid MesProRouteProductBomSaveReqVO createReqVO); + + /** + * 更新工艺路线产品 BOM + */ + void updateRouteProductBom(@Valid MesProRouteProductBomSaveReqVO updateReqVO); + + /** + * 删除工艺路线产品 BOM + */ + void deleteRouteProductBom(Long id); + + /** + * 获得工艺路线产品 BOM + */ + MesProRouteProductBomDO getRouteProductBom(Long id); + + /** + * 按条件查询工艺路线产品 BOM 列表 + */ + List getRouteProductBomList(Long routeId, Long processId, Long productId); + + /** + * 按工艺路线删除产品 BOM(级联删除使用) + * + * @param routeId 工艺路线编号 + */ + void deleteRouteProductBomByRouteId(Long routeId); + + /** + * 按工艺路线和产品删除 BOM(产品删除时级联使用) + * + * @param routeId 工艺路线编号 + * @param productId 产品物料编号 + */ + void deleteRouteProductBomByRouteIdAndProductId(Long routeId, Long productId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java new file mode 100644 index 000000000..24aca4b52 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.mes.service.pro.route; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteProductBomMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 工艺路线产品 BOM Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomService { + + @Resource + private MesProRouteProductBomMapper routeProductBomMapper; + + @Resource + @Lazy + private MesProRouteService routeService; + + @Override + public Long createRouteProductBom(MesProRouteProductBomSaveReqVO createReqVO) { + // 1.0 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(createReqVO.getRouteId()); + // 1.1 校验唯一性 + validateBomUnique(null, createReqVO.getItemId(), createReqVO.getProcessId(), createReqVO.getProductId()); + // 2. 插入 + MesProRouteProductBomDO routeProductBom = BeanUtils.toBean(createReqVO, MesProRouteProductBomDO.class); + routeProductBomMapper.insert(routeProductBom); + return routeProductBom.getId(); + } + + @Override + public void updateRouteProductBom(MesProRouteProductBomSaveReqVO updateReqVO) { + // 1.0 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(updateReqVO.getRouteId()); + // 1.1 校验存在 + validateRouteProductBomExists(updateReqVO.getId()); + // 1.2 校验唯一性 + validateBomUnique(updateReqVO.getId(), updateReqVO.getItemId(), updateReqVO.getProcessId(), updateReqVO.getProductId()); + // 3. 更新 + MesProRouteProductBomDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteProductBomDO.class); + routeProductBomMapper.updateById(updateObj); + } + + @Override + public void deleteRouteProductBom(Long id) { + // 1.1 校验存在 + MesProRouteProductBomDO bom = routeProductBomMapper.selectById(id); + if (bom == null) { + throw exception(PRO_ROUTE_PRODUCT_BOM_NOT_EXISTS); + } + // 1.2 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(bom.getRouteId()); + // 2. 删除 + routeProductBomMapper.deleteById(id); + } + + private void validateRouteProductBomExists(Long id) { + if (routeProductBomMapper.selectById(id) == null) { + throw exception(PRO_ROUTE_PRODUCT_BOM_NOT_EXISTS); + } + } + + private void validateBomUnique(Long id, Long itemId, Long processId, Long productId) { + MesProRouteProductBomDO existing = routeProductBomMapper.selectByUnique(itemId, processId, productId); + if (existing == null) { + return; + } + if (ObjUtil.notEqual(existing.getId(), id)) { + throw exception(PRO_ROUTE_PRODUCT_BOM_DUPLICATE); + } + } + + @Override + public MesProRouteProductBomDO getRouteProductBom(Long id) { + return routeProductBomMapper.selectById(id); + } + + @Override + public List getRouteProductBomList(Long routeId, Long processId, Long productId) { + return routeProductBomMapper.selectList(routeId, processId, productId); + } + + @Override + public void deleteRouteProductBomByRouteId(Long routeId) { + routeProductBomMapper.deleteByRouteId(routeId); + } + + @Override + public void deleteRouteProductBomByRouteIdAndProductId(Long routeId, Long productId) { + routeProductBomMapper.deleteByRouteIdAndProductId(routeId, productId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductService.java new file mode 100644 index 000000000..370697d68 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductService.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.service.pro.route; + +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 工艺路线产品 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProRouteProductService { + + /** + * 创建工艺路线产品 + */ + Long createRouteProduct(@Valid MesProRouteProductSaveReqVO createReqVO); + + /** + * 更新工艺路线产品 + */ + void updateRouteProduct(@Valid MesProRouteProductSaveReqVO updateReqVO); + + /** + * 删除工艺路线产品 + */ + void deleteRouteProduct(Long id); + + /** + * 获得工艺路线产品 + */ + MesProRouteProductDO getRouteProduct(Long id); + + /** + * 按产品(物料)获得工艺路线产品 + * + * @param itemId 产品编号 + * @return 工艺路线产品,如果未配置则返回 null + */ + MesProRouteProductDO getRouteProductByItemId(Long itemId); + + /** + * 按工艺路线获得产品列表 + */ + List getRouteProductListByRouteId(Long routeId); + + /** + * 按工艺路线删除产品(级联删除使用) + * + * @param routeId 工艺路线编号 + */ + void deleteRouteProductByRouteId(Long routeId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductServiceImpl.java new file mode 100644 index 000000000..8d1effc6b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductServiceImpl.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.mes.service.pro.route; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteProductMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 工艺路线产品 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProRouteProductServiceImpl implements MesProRouteProductService { + + @Resource + private MesProRouteProductMapper routeProductMapper; + + @Resource + @Lazy + private MesProRouteService routeService; + @Resource + @Lazy + private MesProRouteProductBomService routeProductBomService; + + @Override + public Long createRouteProduct(MesProRouteProductSaveReqVO createReqVO) { + // 1.0 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(createReqVO.getRouteId()); + // 1.1 校验产品唯一性(一个产品只能关联一条工艺路线) + validateItemUnique(null, createReqVO.getItemId()); + + // 2. 插入 + MesProRouteProductDO routeProduct = BeanUtils.toBean(createReqVO, MesProRouteProductDO.class); + routeProductMapper.insert(routeProduct); + return routeProduct.getId(); + } + + @Override + public void updateRouteProduct(MesProRouteProductSaveReqVO updateReqVO) { + // 1.0 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(updateReqVO.getRouteId()); + // 1.1 校验存在 + validateRouteProductExists(updateReqVO.getId()); + // 1.2 校验产品唯一性 + validateItemUnique(updateReqVO.getId(), updateReqVO.getItemId()); + + // 2. 更新 + MesProRouteProductDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteProductDO.class); + routeProductMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteRouteProduct(Long id) { + // 1.1 校验存在 + MesProRouteProductDO routeProduct = routeProductMapper.selectById(id); + validateRouteProductExists(routeProduct); + // 1.2 已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(routeProduct.getRouteId()); + + // 2.1 级联删除关联的 BOM + routeProductBomService.deleteRouteProductBomByRouteIdAndProductId(routeProduct.getRouteId(), routeProduct.getItemId()); + // 2.2 删除产品关联 + routeProductMapper.deleteById(id); + } + + private void validateRouteProductExists(Long id) { + if (routeProductMapper.selectById(id) == null) { + throw exception(PRO_ROUTE_PRODUCT_NOT_EXISTS); + } + } + + private void validateRouteProductExists(MesProRouteProductDO routeProduct) { + if (routeProduct == null) { + throw exception(PRO_ROUTE_PRODUCT_NOT_EXISTS); + } + } + + private void validateItemUnique(Long id, Long itemId) { + MesProRouteProductDO existing = routeProductMapper.selectByItemId(itemId); + if (existing == null) { + return; + } + if (ObjUtil.notEqual(existing.getId(), id)) { + throw exception(PRO_ROUTE_PRODUCT_ITEM_DUPLICATE); + } + } + + @Override + public MesProRouteProductDO getRouteProduct(Long id) { + return routeProductMapper.selectById(id); + } + + @Override + public MesProRouteProductDO getRouteProductByItemId(Long itemId) { + return routeProductMapper.selectByItemId(itemId); + } + + @Override + public List getRouteProductListByRouteId(Long routeId) { + return routeProductMapper.selectListByRouteId(routeId); + } + + @Override + public void deleteRouteProductByRouteId(Long routeId) { + routeProductMapper.deleteByRouteId(routeId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteService.java new file mode 100644 index 000000000..abdf44b3e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteService.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.service.pro.route; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.MesProRoutePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.MesProRouteSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 工艺路线 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProRouteService { + + /** + * 创建工艺路线 + */ + Long createRoute(@Valid MesProRouteSaveReqVO createReqVO); + + /** + * 更新工艺路线 + */ + void updateRoute(@Valid MesProRouteSaveReqVO updateReqVO); + + /** + * 更新工艺路线状态(启用/禁用) + * + * @param id 编号 + * @param status 状态 + */ + void updateRouteStatus(Long id, Integer status); + + /** + * 删除工艺路线 + */ + void deleteRoute(Long id); + + /** + * 获得工艺路线 + */ + MesProRouteDO getRoute(Long id); + + /** + * 获得工艺路线分页 + */ + PageResult getRoutePage(MesProRoutePageReqVO pageReqVO); + + /** + * 获得启用状态的工艺路线列表 + */ + List getRouteListByStatus(Integer status); + + /** + * 校验工艺路线未启用(已启用则抛异常) + * + * @param routeId 工艺路线编号 + */ + void validateRouteNotEnable(Long routeId); + + /** + * 校验工艺路线存在 + * + * @param id 工艺路线编号 + * @return 工艺路线 + */ + MesProRouteDO validateRouteExists(Long id); + + /** + * 获得工艺路线列表 + * + * @param ids 编号数组 + * @return 工艺路线列表 + */ + List getRouteList(Collection ids); + + /** + * 获得工艺路线 Map + * + * @param ids 编号数组 + * @return 工艺路线 Map + */ + default Map getRouteMap(Collection ids) { + return convertMap(getRouteList(ids), MesProRouteDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteServiceImpl.java new file mode 100644 index 000000000..7db3bd263 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteServiceImpl.java @@ -0,0 +1,184 @@ +package cn.iocoder.yudao.module.mes.service.pro.route; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.MesProRoutePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.MesProRouteSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 工艺路线 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProRouteServiceImpl implements MesProRouteService { + + @Resource + private MesProRouteMapper routeMapper; + + @Resource + @Lazy + private MesProRouteProcessService routeProcessService; + @Resource + @Lazy + private MesProRouteProductService routeProductService; + @Resource + @Lazy + private MesProRouteProductBomService routeProductBomService; + @Resource + @Lazy + private MesMdItemService itemService; + + @Override + public Long createRoute(MesProRouteSaveReqVO createReqVO) { + // 1. 校验编码唯一性 + validateRouteCodeUnique(null, createReqVO.getCode()); + // 2. 插入 + MesProRouteDO route = BeanUtils.toBean(createReqVO, MesProRouteDO.class); + route.setStatus(CommonStatusEnum.DISABLE.getStatus()); + routeMapper.insert(route); + return route.getId(); + } + + @Override + public void updateRoute(MesProRouteSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateRouteExists(updateReqVO.getId()); + // 1.2 校验编码唯一性 + validateRouteCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 2. 更新 + MesProRouteDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteDO.class); + routeMapper.updateById(updateObj); + } + + @Override + public void updateRouteStatus(Long id, Integer status) { + // 1.1 校验存在 + MesProRouteDO route = validateRouteExists(id); + // 1.2 启用时的校验 + if (CommonStatusEnum.ENABLE.getStatus().equals(status)) { + validateRouteEnable(id); + } + + // 2. 更新状态 + routeMapper.updateById(new MesProRouteDO().setId(id).setStatus(status)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteRoute(Long id) { + // 1.1 校验存在 + validateRouteExists(id); + // 1.2 已启用的工艺路线,不允许删除 + validateRouteNotEnable(id); + + // 2.1 级联删除 + routeProcessService.deleteRouteProcessByRouteId(id); + routeProductService.deleteRouteProductByRouteId(id); + routeProductBomService.deleteRouteProductBomByRouteId(id); + // 2.2 删除工艺路线 + routeMapper.deleteById(id); + } + + @Override + public MesProRouteDO validateRouteExists(Long id) { + MesProRouteDO route = routeMapper.selectById(id); + if (route == null) { + throw exception(PRO_ROUTE_NOT_EXISTS); + } + return route; + } + + private void validateRouteCodeUnique(Long id, String code) { + MesProRouteDO route = routeMapper.selectByCode(code); + if (route == null) { + return; + } + if (ObjUtil.notEqual(route.getId(), id)) { + throw exception(PRO_ROUTE_CODE_DUPLICATE); + } + } + + /** + * 启用工艺路线时的校验 + */ + private void validateRouteEnable(Long routeId) { + // 1. 必须有工序 + List processList = routeProcessService.getRouteProcessListByRouteId(routeId); + if (CollUtil.isEmpty(processList)) { + throw exception(PRO_ROUTE_ENABLE_NO_PROCESS); + } + // 2. 必须有关键工序 + boolean hasKeyProcess = processList.stream().anyMatch(MesProRouteProcessDO::getKeyFlag); + if (BooleanUtil.isFalse(hasKeyProcess)) { + throw exception(PRO_ROUTE_ENABLE_NO_KEY_PROCESS); + } + // 3. 所有产品必须配置了 BOM 消耗 + List productList = routeProductService.getRouteProductListByRouteId(routeId); + for (MesProRouteProductDO product : productList) { + List bomList = routeProductBomService + .getRouteProductBomList(routeId, null, product.getItemId()); + if (CollUtil.isEmpty(bomList)) { + MesMdItemDO item = itemService.validateItemExists(product.getItemId()); + throw exception(PRO_ROUTE_ENABLE_PRODUCT_NO_BOM, item.getName()); + } + } + } + + @Override + public MesProRouteDO getRoute(Long id) { + return routeMapper.selectById(id); + } + + @Override + public PageResult getRoutePage(MesProRoutePageReqVO pageReqVO) { + return routeMapper.selectPage(pageReqVO); + } + + @Override + public List getRouteListByStatus(Integer status) { + return routeMapper.selectListByStatus(status); + } + + @Override + public void validateRouteNotEnable(Long routeId) { + MesProRouteDO route = routeMapper.selectById(routeId); + if (route != null && CommonStatusEnum.ENABLE.getStatus().equals(route.getStatus())) { + throw exception(PRO_ROUTE_IS_ENABLE); + } + } + + @Override + public List getRouteList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return routeMapper.selectByIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueService.java new file mode 100644 index 000000000..68835683b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueService.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.service.pro.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskIssueDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 生产任务投料 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProTaskIssueService { + + /** + * 创建生产任务投料 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTaskIssue(@Valid MesProTaskIssueSaveReqVO createReqVO); + + /** + * 更新生产任务投料 + * + * @param updateReqVO 更新信息 + */ + void updateTaskIssue(@Valid MesProTaskIssueSaveReqVO updateReqVO); + + /** + * 删除生产任务投料 + * + * @param id 编号 + */ + void deleteTaskIssue(Long id); + + /** + * 获得生产任务投料 + * + * @param id 编号 + * @return 生产任务投料 + */ + MesProTaskIssueDO getTaskIssue(Long id); + + /** + * 获得生产任务投料分页 + * + * @param pageReqVO 分页查询 + * @return 生产任务投料分页 + */ + PageResult getTaskIssuePage(MesProTaskIssuePageReqVO pageReqVO); + + /** + * 根据任务编号,获得投料列表 + * + * @param taskId 任务编号 + * @return 投料列表 + */ + List getTaskIssueListByTaskId(Long taskId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueServiceImpl.java new file mode 100644 index 000000000..713ca6583 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueServiceImpl.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.service.pro.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskIssueDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskIssueMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_ISSUE_NOT_EXISTS; + +/** + * MES 生产任务投料 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProTaskIssueServiceImpl implements MesProTaskIssueService { + + @Resource + private MesProTaskIssueMapper taskIssueMapper; + + @Resource + private MesProTaskService taskService; + + @Resource + private MesMdItemService itemService; + + @Override + public Long createTaskIssue(MesProTaskIssueSaveReqVO createReqVO) { + // 1. 校验关联数据存在 + taskService.validateTaskExists(createReqVO.getTaskId()); + if (createReqVO.getItemId() != null) { + itemService.validateItemExists(createReqVO.getItemId()); + } + // 2. 插入 + MesProTaskIssueDO taskIssue = BeanUtils.toBean(createReqVO, MesProTaskIssueDO.class); + taskIssueMapper.insert(taskIssue); + return taskIssue.getId(); + } + + @Override + public void updateTaskIssue(MesProTaskIssueSaveReqVO updateReqVO) { + // 1. 校验存在 + validateTaskIssueExists(updateReqVO.getId()); + // 2. 校验关联数据存在 + if (updateReqVO.getItemId() != null) { + itemService.validateItemExists(updateReqVO.getItemId()); + } + // 3. 更新 + MesProTaskIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesProTaskIssueDO.class); + taskIssueMapper.updateById(updateObj); + } + + @Override + public void deleteTaskIssue(Long id) { + // 1. 校验存在 + validateTaskIssueExists(id); + + // 2. 删除 + taskIssueMapper.deleteById(id); + } + + @Override + public MesProTaskIssueDO getTaskIssue(Long id) { + return taskIssueMapper.selectById(id); + } + + @Override + public PageResult getTaskIssuePage(MesProTaskIssuePageReqVO pageReqVO) { + return taskIssueMapper.selectPage(pageReqVO); + } + + @Override + public List getTaskIssueListByTaskId(Long taskId) { + return taskIssueMapper.selectListByTaskId(taskId); + } + + private void validateTaskIssueExists(Long id) { + if (taskIssueMapper.selectById(id) == null) { + throw exception(PRO_TASK_ISSUE_NOT_EXISTS); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java new file mode 100644 index 000000000..a65fa82e1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java @@ -0,0 +1,138 @@ +package cn.iocoder.yudao.module.mes.service.pro.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 生产任务 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProTaskService { + + /** + * 创建生产任务 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTask(@Valid MesProTaskSaveReqVO createReqVO); + + /** + * 更新生产任务 + * + * @param updateReqVO 更新信息 + */ + void updateTask(@Valid MesProTaskSaveReqVO updateReqVO); + + /** + * 删除生产任务 + * + * @param id 编号 + */ + void deleteTask(Long id); + + /** + * 获得生产任务 + * + * @param id 编号 + * @return 生产任务 + */ + MesProTaskDO getTask(Long id); + + /** + * 获得生产任务分页 + * + * @param pageReqVO 分页查询 + * @return 生产任务分页 + */ + PageResult getTaskPage(MesProTaskPageReqVO pageReqVO); + + /** + * 获得生产任务精简列表 + * + * @param workOrderId 工单编号(可选) + * @return 生产任务列表 + */ + List getTaskListByWorkOrderId(Long workOrderId); + + /** + * 根据工单编号列表,批量获得生产任务列表 + * + * @param workOrderIds 工单编号列表 + * @return 生产任务列表 + */ + List getTaskListByWorkOrderIds(Collection workOrderIds); + + /** + * 校验任务是否存在 + * + * @param id 编号 + * @return 生产任务 + */ + MesProTaskDO validateTaskExists(Long id); + + /** + * 校验任务存在且未完成(非终态) + * + * @param id 编号 + * @return 生产任务 + */ + MesProTaskDO validateTaskNotFinished(Long id); + + /** + * 获得生产任务列表 + * + * @param ids 编号列表 + * @return 生产任务列表 + */ + List getTaskList(Collection ids); + + /** + * 获得生产任务 Map + * + * @param ids 编号列表 + * @return 生产任务 Map + */ + default Map getTaskMap(Collection ids) { + return convertMap(getTaskList(ids), MesProTaskDO::getId); + } + + /** + * 根据工单编号,完成所有关联任务 + * + * @param workOrderId 工单编号 + */ + void finishTaskByOrderId(Long workOrderId); + + /** + * 根据工单编号,取消所有关联任务 + * + * @param workOrderId 工单编号 + */ + void cancelTaskByOrderId(Long workOrderId); + + /** + * 累加任务的已生产、合格、不合格数量 + * + * @param id 任务编号 + * @param incrProducedQuantity 本次已生产数量增量(不良品也计入) + * @param incrQualifyQuantity 本次合格品数量增量 + * @param incrUnqualifyQuantity 本次不合格品数量增量 + */ + void updateProducedQuantity(Long id, + BigDecimal incrProducedQuantity, + BigDecimal incrQualifyQuantity, + BigDecimal incrUnqualifyQuantity); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java new file mode 100644 index 000000000..a976aa49e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java @@ -0,0 +1,232 @@ +package cn.iocoder.yudao.module.mes.service.pro.task; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskSaveReqVO; +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.task.MesProTaskDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskMapper; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; +import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; +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.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_ALREADY_FINISHED; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_EXISTS; + +/** + * MES 生产任务 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProTaskServiceImpl implements MesProTaskService { + + @Resource + private MesProTaskMapper taskMapper; + + @Resource + @Lazy + private MesProWorkOrderService workOrderService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesProProcessService processService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesProRouteService routeService; + @Resource + private MesMdAutoCodeRecordService autoCodeRecordService; + + @Override + public Long createTask(MesProTaskSaveReqVO createReqVO) { + // 1. 校验关联数据存在 + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); + workstationService.validateWorkstationExists(createReqVO.getWorkstationId()); + routeService.validateRouteExists(createReqVO.getRouteId()); + processService.validateProcessExists(createReqVO.getProcessId()); + MesMdItemDO item = itemService.validateItemExists(createReqVO.getItemId()); + + // 2.1 构建任务 DO:自动填充客户信息 + MesProTaskDO task = BeanUtils.toBean(createReqVO, MesProTaskDO.class) + .setName(buildTaskName(item, createReqVO.getQuantity())) + .setCode(autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.PRO_TASK_CODE.getCode())) + .setStatus(MesProTaskStatusEnum.PREPARE.getStatus()); + if (task.getClientId() == null && workOrder.getClientId() != null) { + task.setClientId(workOrder.getClientId()); + } + // 2.2 插入 + taskMapper.insert(task); + return task.getId(); + } + + @Override + public void updateTask(MesProTaskSaveReqVO updateReqVO) { + // 1.1 校验存在 + MesProTaskDO task = validateTaskExists(updateReqVO.getId()); + // 1.2 校验关联数据存在 + if (updateReqVO.getWorkOrderId() != null) { + workOrderService.validateWorkOrderExists(updateReqVO.getWorkOrderId()); + } + if (updateReqVO.getWorkstationId() != null) { + workstationService.validateWorkstationExists(updateReqVO.getWorkstationId()); + } + if (updateReqVO.getRouteId() != null) { + routeService.validateRouteExists(updateReqVO.getRouteId()); + } + if (updateReqVO.getProcessId() != null) { + processService.validateProcessExists(updateReqVO.getProcessId()); + } + MesMdItemDO item; + if (updateReqVO.getItemId() != null) { + item = itemService.validateItemExists(updateReqVO.getItemId()); + } else { + item = itemService.validateItemExists(task.getItemId()); + } + BigDecimal quantity = updateReqVO.getQuantity() != null ? updateReqVO.getQuantity() : task.getQuantity(); + + // 2. 更新 + MesProTaskDO updateObj = BeanUtils.toBean(updateReqVO, MesProTaskDO.class) + .setName(buildTaskName(item, quantity)); + taskMapper.updateById(updateObj); + } + + /** + * 构建任务名称,格式:"产品名【数量】单位" + */ + private String buildTaskName(MesMdItemDO item, BigDecimal quantity) { + String unitName = ""; + if (item.getUnitMeasureId() != null) { + MesMdUnitMeasureDO unit = unitMeasureService.getUnitMeasure(item.getUnitMeasureId()); + if (unit != null) { + unitName = unit.getName(); + } + } + return item.getName() + "【" + quantity + "】" + unitName; + } + + @Override + public void deleteTask(Long id) { + // 1. 校验存在且非终态 + validateTaskNotFinished(id); + + // 2. 删除 + taskMapper.deleteById(id); + } + + @Override + public MesProTaskDO getTask(Long id) { + return taskMapper.selectById(id); + } + + @Override + public PageResult getTaskPage(MesProTaskPageReqVO pageReqVO) { + return taskMapper.selectPage(pageReqVO); + } + + @Override + public List getTaskListByWorkOrderId(Long workOrderId) { + return taskMapper.selectListByWorkOrderId(workOrderId); + } + + @Override + public List getTaskListByWorkOrderIds(Collection workOrderIds) { + if (CollUtil.isEmpty(workOrderIds)) { + return Collections.emptyList(); + } + return taskMapper.selectListByWorkOrderIds(workOrderIds); + } + + @Override + public MesProTaskDO validateTaskExists(Long id) { + MesProTaskDO task = taskMapper.selectById(id); + if (task == null) { + throw exception(PRO_TASK_NOT_EXISTS); + } + return task; + } + + @Override + public MesProTaskDO validateTaskNotFinished(Long id) { + MesProTaskDO task = validateTaskExists(id); + if (MesProTaskStatusEnum.isEndStatus(task.getStatus())) { + throw exception(PRO_TASK_ALREADY_FINISHED); + } + return task; + } + + @Override + public List getTaskList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return taskMapper.selectByIds(ids); + } + + @Override + public void finishTaskByOrderId(Long workOrderId) { + // 1. 读取工单下所有任务,过滤掉已完成/已取消的 + List tasks = taskMapper.selectListByWorkOrderId(workOrderId); + LocalDateTime now = LocalDateTime.now(); + // 2. 构建待更新列表,批量更新 + List updateList = convertList(tasks, + task -> new MesProTaskDO().setId(task.getId()) + .setStatus(MesProTaskStatusEnum.FINISHED.getStatus()).setFinishDate(now), + task -> !MesProTaskStatusEnum.isEndStatus(task.getStatus())); + if (CollUtil.isNotEmpty(updateList)) { + taskMapper.updateBatch(updateList); + } + } + + @Override + public void cancelTaskByOrderId(Long workOrderId) { + // 1. 读取工单下所有任务,过滤掉已完成/已取消的 + List tasks = taskMapper.selectListByWorkOrderId(workOrderId); + LocalDateTime now = LocalDateTime.now(); + // 2. 构建待更新列表,批量更新 + List updateList = convertList(tasks, + task -> new MesProTaskDO().setId(task.getId()) + .setStatus(MesProTaskStatusEnum.CANCELED.getStatus()).setCancelDate(now), + task -> !MesProTaskStatusEnum.isEndStatus(task.getStatus())); + if (CollUtil.isNotEmpty(updateList)) { + taskMapper.updateBatch(updateList); + } + } + + @Override + public void updateProducedQuantity(Long id, + BigDecimal incrProducedQuantity, + BigDecimal incrQualifyQuantity, + BigDecimal incrUnqualifyQuantity) { + // 校验任务存在 + validateTaskExists(id); + // 更新数量 + taskMapper.updateProducedQuantity(id, incrProducedQuantity, incrQualifyQuantity, incrUnqualifyQuantity); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomService.java new file mode 100644 index 000000000..b6ec56a10 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomService.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.mes.service.pro.workorder; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 生产工单 BOM Service 接口 + * + * @author 芋道源码 + */ +public interface MesProWorkOrderBomService { + + /** + * 创建工单 BOM + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkOrderBom(@Valid MesProWorkOrderBomSaveReqVO createReqVO); + + /** + * 更新工单 BOM + * + * @param updateReqVO 更新信息 + */ + void updateWorkOrderBom(@Valid MesProWorkOrderBomSaveReqVO updateReqVO); + + /** + * 删除工单 BOM + * + * @param id 编号 + */ + void deleteWorkOrderBom(Long id); + + /** + * 获得工单 BOM + * + * @param id 编号 + * @return 工单 BOM + */ + MesProWorkOrderBomDO getWorkOrderBom(Long id); + + /** + * 获得工单 BOM 分页 + * + * @param pageReqVO 分页查询 + * @return 工单 BOM 分页 + */ + PageResult getWorkOrderBomPage(MesProWorkOrderBomPageReqVO pageReqVO); + + /** + * 根据工单编号获得 BOM 列表 + * + * @param workOrderId 工单编号 + * @return BOM 列表 + */ + List getWorkOrderBomListByWorkOrderId(Long workOrderId); + + /** + * 根据工单编号删除 BOM + * + * @param workOrderId 工单编号 + */ + void deleteWorkOrderBomByWorkOrderId(Long workOrderId); + + /** + * 根据产品 BOM 自动生成工单 BOM 行 + *

+ * 如果 updated 为 true,会先清理旧的 BOM 数据再重新生成 + * + * @param workOrderId 工单编号 + * @param reqVO 工单创建/更新请求(取 productId、quantity) + * @param updated 是否为更新场景(true 时先删除旧 BOM) + */ + void generateWorkOrderBom(Long workOrderId, MesProWorkOrderSaveReqVO reqVO, boolean updated); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomServiceImpl.java new file mode 100644 index 000000000..f995cd0e4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomServiceImpl.java @@ -0,0 +1,136 @@ +package cn.iocoder.yudao.module.mes.service.pro.workorder; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderBomMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductBomService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_WORK_ORDER_BOM_NOT_EXISTS; + +/** + * MES 生产工单 BOM Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService { + + @Resource + private MesProWorkOrderBomMapper workOrderBomMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private MesProWorkOrderService workOrderService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdProductBomService productBomService; + + @Override + public Long createWorkOrderBom(MesProWorkOrderBomSaveReqVO createReqVO) { + // 校验工单存在 + workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); + + // 插入数据 + MesProWorkOrderBomDO workOrderBom = BeanUtils.toBean(createReqVO, MesProWorkOrderBomDO.class); + workOrderBomMapper.insert(workOrderBom); + return workOrderBom.getId(); + } + + @Override + public void updateWorkOrderBom(MesProWorkOrderBomSaveReqVO updateReqVO) { + // 校验存在 + validateWorkOrderBomExists(updateReqVO.getId()); + + // 更新数据 + MesProWorkOrderBomDO updateObj = BeanUtils.toBean(updateReqVO, MesProWorkOrderBomDO.class); + workOrderBomMapper.updateById(updateObj); + } + + @Override + public void deleteWorkOrderBom(Long id) { + // 校验存在 + validateWorkOrderBomExists(id); + + // 删除 + workOrderBomMapper.deleteById(id); + } + + private void validateWorkOrderBomExists(Long id) { + if (workOrderBomMapper.selectById(id) == null) { + throw exception(PRO_WORK_ORDER_BOM_NOT_EXISTS); + } + } + + @Override + public MesProWorkOrderBomDO getWorkOrderBom(Long id) { + return workOrderBomMapper.selectById(id); + } + + @Override + public PageResult getWorkOrderBomPage(MesProWorkOrderBomPageReqVO pageReqVO) { + return workOrderBomMapper.selectPage(pageReqVO); + } + + @Override + public List getWorkOrderBomListByWorkOrderId(Long workOrderId) { + return workOrderBomMapper.selectListByWorkOrderId(workOrderId); + } + + @Override + public void deleteWorkOrderBomByWorkOrderId(Long workOrderId) { + workOrderBomMapper.deleteByWorkOrderId(workOrderId); + } + + @Override + public void generateWorkOrderBom(Long workOrderId, MesProWorkOrderSaveReqVO reqVO, boolean updated) { + // 1. 如果是更新场景,先清理旧的 BOM 数据 + if (updated) { + workOrderBomMapper.deleteByWorkOrderId(workOrderId); + } + + // 2.1 查询产品 BOM + List productBomList = productBomService.getProductBomListByItemId(reqVO.getProductId()); + if (CollUtil.isEmpty(productBomList)) { + return; + } + // 2.2 批量获取并校验 BOM 物料 + Set bomItemIds = convertSet(productBomList, MesMdProductBomDO::getBomItemId); + Map itemMap = itemService.getItemMap(bomItemIds); + bomItemIds.forEach(itemId -> { + if (itemMap.get(itemId) == null) { + throw exception(MD_ITEM_NOT_EXISTS); + } + }); + + // 3. 构建工单 BOM 列表并批量插入 + List bomList = new ArrayList<>(productBomList.size()); + for (MesMdProductBomDO productBom : productBomList) { + bomList.add(new MesProWorkOrderBomDO().setWorkOrderId(workOrderId).setItemId(productBom.getBomItemId()) + .setQuantity(reqVO.getQuantity().multiply(productBom.getQuantity()))); + } + workOrderBomMapper.insertBatch(bomList); + } + +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java new file mode 100644 index 000000000..9aa713e45 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java @@ -0,0 +1,132 @@ +package cn.iocoder.yudao.module.mes.service.pro.workorder; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 生产工单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProWorkOrderService { + + /** + * 创建生产工单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWorkOrder(@Valid MesProWorkOrderSaveReqVO createReqVO); + + /** + * 更新生产工单 + * + * @param updateReqVO 更新信息 + */ + void updateWorkOrder(@Valid MesProWorkOrderSaveReqVO updateReqVO); + + /** + * 删除生产工单 + * + * @param id 编号 + */ + void deleteWorkOrder(Long id); + + /** + * 校验生产工单存在 + * + * @param id 编号 + * @return 生产工单 + */ + MesProWorkOrderDO validateWorkOrderExists(Long id); + + /** + * 获得生产工单 + * + * @param id 编号 + * @return 生产工单 + */ + MesProWorkOrderDO getWorkOrder(Long id); + + /** + * 根据编码获得生产工单 + * + * @param code 编码 + * @return 生产工单 + */ + MesProWorkOrderDO getWorkOrder(String code); + + /** + * 获得生产工单分页 + * + * @param pageReqVO 分页查询 + * @return 生产工单分页 + */ + PageResult getWorkOrderPage(MesProWorkOrderPageReqVO pageReqVO); + + /** + * 获得工单列表 + * + * @param ids 编号数组 + * @return 工单列表 + */ + List getWorkOrderList(Collection ids); + + /** + * 获得工单 Map + * + * @param ids 编号数组 + * @return 工单 Map + */ + default Map getWorkOrderMap(Collection ids) { + return convertMap(getWorkOrderList(ids), MesProWorkOrderDO::getId); + } + + /** + * 校验工单已确认 + * + * @param id 编号 + * @return 工单 + */ + MesProWorkOrderDO validateWorkOrderConfirmed(Long id); + + /** + * 确认工单(草稿 → 已确认) + * + * @param id 编号 + */ + void confirmWorkOrder(Long id); + + /** + * 完成工单 + * + * @param id 编号 + */ + void finishWorkOrder(Long id); + + /** + * 取消工单 + * + * @param id 编号 + */ + void cancelWorkOrder(Long id); + + /** + * 累加工单的已生产数量 + * + * @param id 工单编号 + * @param incrQuantityProduced 本次已生产数量增量 + */ + void updateProducedQuantity(Long id, BigDecimal incrQuantityProduced); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java new file mode 100644 index 000000000..431b08493 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java @@ -0,0 +1,248 @@ +package cn.iocoder.yudao.module.mes.service.pro.workorder; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderMapper; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemBatchConfigService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 生产工单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { + + @Resource + private MesProWorkOrderMapper workOrderMapper; + + @Resource + private MesProWorkOrderBomService workOrderBomService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdItemBatchConfigService itemBatchConfigService; + @Resource + private MesWmBarcodeService barcodeService; + @Resource + private MesProTaskService taskService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createWorkOrder(MesProWorkOrderSaveReqVO createReqVO) { + // 1. 校验数据 + validateWorkOrderSaveData(null, createReqVO); + + // 2.1 设置默认值 + if (createReqVO.getParentId() == null) { + createReqVO.setParentId(MesProWorkOrderDO.PARENT_ID_NULL); + } + // 2.2 插入工单 + MesProWorkOrderDO workOrder = BeanUtils.toBean(createReqVO, MesProWorkOrderDO.class); + workOrder.setStatus(MesProWorkOrderStatusEnum.PREPARE.getStatus()); + workOrderMapper.insert(workOrder); + + // 3. 自动生成 BOM:根据产品 BOM 生成工单 BOM + workOrderBomService.generateWorkOrderBom(workOrder.getId(), createReqVO, false); + + // 4. 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.WORKORDER.getValue(), + workOrder.getId(), workOrder.getCode(), workOrder.getName()); + return workOrder.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateWorkOrder(MesProWorkOrderSaveReqVO updateReqVO) { + // 1.1 校验存在 + 只有草稿状态才能编辑 + MesProWorkOrderDO oldWorkOrder = validateWorkOrderExists(updateReqVO.getId()); + if (ObjUtil.notEqual(oldWorkOrder.getStatus(), MesProWorkOrderStatusEnum.PREPARE.getStatus())) { + throw exception(PRO_WORK_ORDER_NOT_PREPARE); + } + // 1.2 校验数据 + validateWorkOrderSaveData(updateReqVO.getId(), updateReqVO); + + // 2. 判断产品或数量是否变更,如果变更则重新生成 BOM(updated=true 会先清理旧数据) + boolean productChanged = ObjUtil.notEqual(oldWorkOrder.getProductId(), updateReqVO.getProductId()); + boolean quantityChanged = oldWorkOrder.getQuantity().compareTo(updateReqVO.getQuantity()) != 0; + if (productChanged || quantityChanged) { + workOrderBomService.generateWorkOrderBom(updateReqVO.getId(), updateReqVO, true); + } + + // 3. 更新 + MesProWorkOrderDO updateObj = BeanUtils.toBean(updateReqVO, MesProWorkOrderDO.class); + workOrderMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteWorkOrder(Long id) { + // 1.1 校验存在 + MesProWorkOrderDO workOrder = validateWorkOrderExists(id); + // 1.2 只能删除草稿状态的工单 + if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.PREPARE.getStatus())) { + throw exception(PRO_WORK_ORDER_NOT_PREPARE); + } + // 1.3 校验是否有子工单 + Long childCount = workOrderMapper.selectCount(MesProWorkOrderDO::getParentId, id); + if (childCount > 0) { + throw exception(PRO_WORK_ORDER_HAS_CHILDREN); + } + + // 2. 删除工单 + BOM + workOrderMapper.deleteById(id); + workOrderBomService.deleteWorkOrderBomByWorkOrderId(id); + } + + @Override + public MesProWorkOrderDO validateWorkOrderExists(Long id) { + MesProWorkOrderDO workOrder = workOrderMapper.selectById(id); + if (workOrder == null) { + throw exception(PRO_WORK_ORDER_NOT_EXISTS); + } + return workOrder; + } + + @Override + public MesProWorkOrderDO getWorkOrder(Long id) { + return workOrderMapper.selectById(id); + } + + @Override + public MesProWorkOrderDO getWorkOrder(String code) { + return workOrderMapper.selectByCode(code); + } + + @Override + public PageResult getWorkOrderPage(MesProWorkOrderPageReqVO pageReqVO) { + return workOrderMapper.selectPage(pageReqVO); + } + + @Override + public List getWorkOrderList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return workOrderMapper.selectByIds(ids); + } + + @Override + public MesProWorkOrderDO validateWorkOrderConfirmed(Long id) { + MesProWorkOrderDO workOrder = validateWorkOrderExists(id); + if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.CONFIRMED.getStatus())) { + throw exception(PRO_WORK_ORDER_NOT_CONFIRMED); + } + return workOrder; + } + + @Override + public void confirmWorkOrder(Long id) { + // 1.1 校验存在 + MesProWorkOrderDO workOrder = validateWorkOrderExists(id); + // 1.2 只有草稿状态才能确认 + if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.PREPARE.getStatus())) { + throw exception(PRO_WORK_ORDER_NOT_PREPARE); + } + + // 2. 更新状态为已确认 + workOrderMapper.updateById(new MesProWorkOrderDO().setId(id) + .setStatus(MesProWorkOrderStatusEnum.CONFIRMED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishWorkOrder(Long id) { + // 1. 校验存在 + 只有已确认状态才能完成 + MesProWorkOrderDO workOrder = validateWorkOrderExists(id); + if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.CONFIRMED.getStatus())) { + throw exception(PRO_WORK_ORDER_NOT_CONFIRMED); + } + + // 2. 级联完成所有关联任务 + taskService.finishTaskByOrderId(id); + + // 3. 更新工单状态为已完成 + workOrderMapper.updateById(new MesProWorkOrderDO().setId(id) + .setStatus(MesProWorkOrderStatusEnum.FINISHED.getStatus()) + .setFinishDate(LocalDateTime.now())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelWorkOrder(Long id) { + // 1. 校验存在 + 只有已确认状态才能取消 + MesProWorkOrderDO workOrder = validateWorkOrderExists(id); + if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.CONFIRMED.getStatus())) { + throw exception(PRO_WORK_ORDER_NOT_CONFIRMED); + } + + // 2. 级联取消所有关联任务 + taskService.cancelTaskByOrderId(id); + + // 3. 更新工单状态为已取消 + workOrderMapper.updateById(new MesProWorkOrderDO().setId(id) + .setStatus(MesProWorkOrderStatusEnum.CANCELED.getStatus()) + .setCancelDate(LocalDateTime.now())); + } + + // ==================== 校验方法 ==================== + + private void validateWorkOrderSaveData(Long id, MesProWorkOrderSaveReqVO reqVO) { + // 1. 校验编码唯一 + validateWorkOrderCodeUnique(id, reqVO.getCode()); + // 2. 校验产品存在 + itemService.validateItemExists(reqVO.getProductId()); + // 3. 校验批次配置(如果产品有 clientFlag=true,则 clientId 必填) + MesMdItemBatchConfigDO batchConfig = itemBatchConfigService.getItemBatchConfigByItemId(reqVO.getProductId()); + if (batchConfig != null && Boolean.TRUE.equals(batchConfig.getClientFlag()) && reqVO.getClientId() == null) { + throw exception(MD_CLIENT_NOT_EXISTS); + } + } + + private void validateWorkOrderCodeUnique(Long id, String code) { + if (code == null) { + return; + } + MesProWorkOrderDO workOrder = workOrderMapper.selectByCode(code); + if (workOrder == null) { + return; + } + if (ObjUtil.notEqual(workOrder.getId(), id)) { + throw exception(PRO_WORK_ORDER_CODE_DUPLICATE); + } + } + + @Override + public void updateProducedQuantity(Long id, BigDecimal incrQuantityProduced) { + // 校验工单存在 + validateWorkOrderExists(id); + // 更新数量 + workOrderMapper.updateProducedQuantity(id, incrQuantityProduced); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordService.java new file mode 100644 index 000000000..a69a888aa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordService.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.mes.service.pro.workrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordLogDO; + +/** + * MES 工作记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesProWorkRecordService { + + /** + * 获得上下工记录流水分页 + * + * @param pageReqVO 分页查询 + * @return 上下工记录流水分页 + */ + PageResult getWorkRecordLogPage(MesProWorkRecordLogPageReqVO pageReqVO); + + /** + * 获得上下工记录流水 + * + * @param id 编号 + * @return 上下工记录流水 + */ + MesProWorkRecordLogDO getWorkRecordLog(Long id); + + /** + * 上线(绑定工作站) + * + * @param userId 用户编号 + * @param workstationId 工作站编号 + * @return 记录编号 + */ + Long clockInWorkRecord(Long userId, Long workstationId); + + /** + * 下线(解绑工作站) + * + * @param userId 用户编号 + * @return 记录编号 + */ + Long clockOutWorkRecord(Long userId); + + /** + * 获取指定用户当前的绑定状态 + * + * @param userId 用户编号 + * @return 绑定关系,如果未绑定则返回 null + */ + MesProWorkRecordDO getWorkRecord(Long userId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordServiceImpl.java new file mode 100644 index 000000000..cc02b9144 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordServiceImpl.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.service.pro.workrecord; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo.MesProWorkRecordLogPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord.MesProWorkRecordLogDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.workrecord.MesProWorkRecordLogMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.workrecord.MesProWorkRecordMapper; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkRecordTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WORK_RECORD_ALREADY_CLOCK_IN; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WORK_RECORD_NOT_CLOCK_IN; + +/** + * MES 工作记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesProWorkRecordServiceImpl implements MesProWorkRecordService { + + @Resource + private MesProWorkRecordLogMapper workRecordLogMapper; + @Resource + private MesProWorkRecordMapper workRecordMapper; + @Resource + private MesMdWorkstationService workstationService; + + @Override + public PageResult getWorkRecordLogPage(MesProWorkRecordLogPageReqVO pageReqVO) { + return workRecordLogMapper.selectPage(pageReqVO); + } + + @Override + public MesProWorkRecordLogDO getWorkRecordLog(Long id) { + return workRecordLogMapper.selectById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long clockInWorkRecord(Long userId, Long workstationId) { + // 1.1 校验工作站是否存在 + workstationService.validateWorkstationExists(workstationId); + // 1.2 校验是否重复上线 + MesProWorkRecordDO record = workRecordMapper.selectByUserId(userId); + if (record != null && ObjUtil.equal(MesProWorkRecordTypeEnum.CLOCK_IN.getType(), record.getType())) { + throw exception(WORK_RECORD_ALREADY_CLOCK_IN); + } + + // 2. 写入上线流水 + MesProWorkRecordLogDO log = MesProWorkRecordLogDO.builder().userId(userId) + .workstationId(workstationId).type(MesProWorkRecordTypeEnum.CLOCK_IN.getType()).build(); + workRecordLogMapper.insert(log); + + // 3. 更新用户工作站状态:如果没有记录,或先删除旧记录 + if (record == null) { + record = MesProWorkRecordDO.builder().userId(userId).workstationId(workstationId) + .type(MesProWorkRecordTypeEnum.CLOCK_IN.getType()).clockInTime(LocalDateTime.now()).build(); + workRecordMapper.insert(record); + } else { + workRecordMapper.updateById(new MesProWorkRecordDO().setId(record.getId()) + .setWorkstationId(workstationId).setType(MesProWorkRecordTypeEnum.CLOCK_IN.getType()) + .setClockInTime(LocalDateTime.now()).setClockOutTime(null)); + } + return log.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long clockOutWorkRecord(Long userId) { + // 1. 校验是否有状态 + MesProWorkRecordDO record = workRecordMapper.selectByUserId(userId); + if (record == null || ObjUtil.notEqual(MesProWorkRecordTypeEnum.CLOCK_IN.getType(), record.getType())) { + throw exception(WORK_RECORD_NOT_CLOCK_IN); + } + + // 2. 写入下线流水 + MesProWorkRecordLogDO log = MesProWorkRecordLogDO.builder().userId(userId) + .workstationId(record.getWorkstationId()).type(MesProWorkRecordTypeEnum.CLOCK_OUT.getType()) + .build(); + workRecordLogMapper.insert(log); + + // 3. 更新用户状态 + workRecordMapper.updateById(new MesProWorkRecordDO().setId(record.getId()) + .setType(MesProWorkRecordTypeEnum.CLOCK_OUT.getType()).setClockOutTime(LocalDateTime.now())); + return log.getId(); + } + + @Override + public MesProWorkRecordDO getWorkRecord(Long userId) { + return workRecordMapper.selectByUserId(userId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defect/MesQcDefectService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defect/MesQcDefectService.java new file mode 100644 index 000000000..0ba088218 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defect/MesQcDefectService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.service.qc.defect; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 缺陷类型 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcDefectService { + + /** + * 创建缺陷类型 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createDefect(@Valid MesQcDefectSaveReqVO createReqVO); + + /** + * 更新缺陷类型 + * + * @param updateReqVO 更新信息 + */ + void updateDefect(@Valid MesQcDefectSaveReqVO updateReqVO); + + /** + * 删除缺陷类型 + * + * @param id 编号 + */ + void deleteDefect(Long id); + + /** + * 获得缺陷类型 + * + * @param id 编号 + * @return 缺陷类型 + */ + MesQcDefectDO getDefect(Long id); + + /** + * 获得缺陷类型分页 + * + * @param pageReqVO 分页查询 + * @return 缺陷类型分页 + */ + PageResult getDefectPage(MesQcDefectPageReqVO pageReqVO); + + /** + * 获得缺陷类型列表 + * + * @return 缺陷类型列表 + */ + List getDefectList(); + + /** + * 获得缺陷类型列表 + * + * @param ids 编号数组 + * @return 缺陷类型列表 + */ + List getDefectList(Collection ids); + + /** + * 获得缺陷类型 Map + * + * @param ids 编号数组 + * @return 缺陷类型 Map + */ + default Map getDefectMap(Collection ids) { + return convertMap(getDefectList(ids), MesQcDefectDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defect/MesQcDefectServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defect/MesQcDefectServiceImpl.java new file mode 100644 index 000000000..feb85e3f9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defect/MesQcDefectServiceImpl.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.mes.service.qc.defect; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.defect.MesQcDefectMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 缺陷类型 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcDefectServiceImpl implements MesQcDefectService { + + @Resource + private MesQcDefectMapper defectMapper; + + @Override + public Long createDefect(MesQcDefectSaveReqVO createReqVO) { + // 校验编码、名称唯一 + validateDefectSaveData(null, createReqVO); + + // 插入 + MesQcDefectDO defect = BeanUtils.toBean(createReqVO, MesQcDefectDO.class); + defectMapper.insert(defect); + return defect.getId(); + } + + @Override + public void updateDefect(MesQcDefectSaveReqVO updateReqVO) { + // 校验存在 + validateDefectExists(updateReqVO.getId()); + // 校验编码、名称唯一 + validateDefectSaveData(updateReqVO.getId(), updateReqVO); + + // 更新 + MesQcDefectDO updateObj = BeanUtils.toBean(updateReqVO, MesQcDefectDO.class); + defectMapper.updateById(updateObj); + } + + @Override + public void deleteDefect(Long id) { + // 校验存在 + validateDefectExists(id); + // 删除 + defectMapper.deleteById(id); + } + + private void validateDefectExists(Long id) { + if (defectMapper.selectById(id) == null) { + throw exception(QC_DEFECT_NOT_EXISTS); + } + } + + private void validateDefectSaveData(Long id, MesQcDefectSaveReqVO reqVO) { + validateDefectCodeUnique(id, reqVO.getCode()); + validateDefectNameUnique(id, reqVO.getName()); + } + + private void validateDefectCodeUnique(Long id, String code) { + MesQcDefectDO defect = defectMapper.selectByCode(code); + if (defect == null) { + return; + } + if (ObjUtil.notEqual(defect.getId(), id)) { + throw exception(QC_DEFECT_CODE_DUPLICATE); + } + } + + private void validateDefectNameUnique(Long id, String name) { + MesQcDefectDO defect = defectMapper.selectByName(name); + if (defect == null) { + return; + } + if (ObjUtil.notEqual(defect.getId(), id)) { + throw exception(QC_DEFECT_NAME_DUPLICATE); + } + } + + @Override + public MesQcDefectDO getDefect(Long id) { + return defectMapper.selectById(id); + } + + @Override + public PageResult getDefectPage(MesQcDefectPageReqVO pageReqVO) { + return defectMapper.selectPage(pageReqVO); + } + + @Override + public List getDefectList() { + return defectMapper.selectList(); + } + + @Override + public List getDefectList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return defectMapper.selectByIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defectrecord/MesQcDefectRecordService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defectrecord/MesQcDefectRecordService.java new file mode 100644 index 000000000..3d0acce18 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defectrecord/MesQcDefectRecordService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.service.qc.defectrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo.MesQcDefectRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo.MesQcDefectRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import jakarta.validation.Valid; + +/** + * MES 质检缺陷记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcDefectRecordService { + + /** + * 创建质检缺陷记录 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createDefectRecord(@Valid MesQcDefectRecordSaveReqVO createReqVO); + + /** + * 更新质检缺陷记录 + * + * @param updateReqVO 更新信息 + */ + void updateDefectRecord(@Valid MesQcDefectRecordSaveReqVO updateReqVO); + + /** + * 删除质检缺陷记录 + * + * @param id 编号 + */ + void deleteDefectRecord(Long id); + + /** + * 获得质检缺陷记录分页 + * + * @param pageReqVO 分页查询 + * @return 质检缺陷记录分页 + */ + PageResult getDefectRecordPage(MesQcDefectRecordPageReqVO pageReqVO); + + /** + * 根据检验类型和检验单 ID 级联删除所有缺陷记录 + * + * @param qcType 检验类型 + * @param qcId 检验单 ID + */ + void deleteListByQcTypeAndQcId(Integer qcType, Long qcId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defectrecord/MesQcDefectRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defectrecord/MesQcDefectRecordServiceImpl.java new file mode 100644 index 000000000..709528247 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defectrecord/MesQcDefectRecordServiceImpl.java @@ -0,0 +1,173 @@ +package cn.iocoder.yudao.module.mes.service.qc.defectrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo.MesQcDefectRecordPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.defectrecord.vo.MesQcDefectRecordSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.defectrecord.MesQcDefectRecordMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; +import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 质检缺陷记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcDefectRecordServiceImpl implements MesQcDefectRecordService { + + @Resource + private MesQcDefectRecordMapper defectRecordMapper; + + @Resource + @Lazy + private MesQcIqcService iqcService; + @Resource + @Lazy + private MesQcIqcLineService iqcLineService; + + @Resource + @Lazy + private MesQcIpqcService ipqcService; + @Resource + @Lazy + private MesQcIpqcLineService ipqcLineService; + + @Resource + @Lazy + private MesQcOqcService oqcService; + @Resource + @Lazy + private MesQcOqcLineService oqcLineService; + + @Resource + @Lazy + private MesQcRqcService rqcService; + @Resource + @Lazy + private MesQcRqcLineService rqcLineService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createDefectRecord(MesQcDefectRecordSaveReqVO createReqVO) { + // 1. 校验检验单和检验行存在 + validateQcAndLineExists(createReqVO.getQcType(), createReqVO.getQcId(), createReqVO.getLineId()); + + // 2. 插入 + MesQcDefectRecordDO record = BeanUtils.toBean(createReqVO, MesQcDefectRecordDO.class); + defectRecordMapper.insert(record); + + // 3. 重新计算缺陷统计 + recalculateDefectStats(createReqVO.getQcType(), createReqVO.getQcId()); + return record.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateDefectRecord(MesQcDefectRecordSaveReqVO updateReqVO) { + // 1. 校验存在 + validateDefectRecordExists(updateReqVO.getId()); + + // 2. 更新 + MesQcDefectRecordDO updateObj = BeanUtils.toBean(updateReqVO, MesQcDefectRecordDO.class); + defectRecordMapper.updateById(updateObj); + + // 3. 重新计算缺陷统计 + recalculateDefectStats(updateReqVO.getQcType(), updateReqVO.getQcId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteDefectRecord(Long id) { + // 1. 校验存在 + MesQcDefectRecordDO record = validateDefectRecordExists(id); + + // 2. 删除 + defectRecordMapper.deleteById(id); + + // 3. 重新计算缺陷统计 + recalculateDefectStats(record.getQcType(), record.getQcId()); + } + + @Override + public PageResult getDefectRecordPage(MesQcDefectRecordPageReqVO pageReqVO) { + return defectRecordMapper.selectPage(pageReqVO); + } + + @Override + public void deleteListByQcTypeAndQcId(Integer qcType, Long qcId) { + defectRecordMapper.deleteByQcTypeAndQcId(qcType, qcId); + } + + // ==================== 校验方法 ==================== + + private void validateQcAndLineExists(Integer qcType, Long qcId, Long lineId) { + if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) { + iqcService.validateIqcExists(qcId); + iqcLineService.validateIqcLineExists(lineId); + } else if (Objects.equals(qcType, MesQcTypeEnum.IPQC.getType())) { + ipqcService.validateIpqcExists(qcId); + ipqcLineService.validateIpqcLineExists(lineId); + } else if (Objects.equals(qcType, MesQcTypeEnum.OQC.getType())) { + oqcService.validateOqcExists(qcId); + oqcLineService.validateOqcLineExists(lineId); + } else if (Objects.equals(qcType, MesQcTypeEnum.RQC.getType())) { + rqcService.validateRqcExists(qcId); + rqcLineService.validateRqcLineExists(lineId); + } else { + throw exception(QC_DEFECT_RECORD_QC_TYPE_UNSUPPORTED); + } + } + + private MesQcDefectRecordDO validateDefectRecordExists(Long id) { + MesQcDefectRecordDO record = defectRecordMapper.selectById(id); + if (record == null) { + throw exception(QC_DEFECT_RECORD_NOT_EXISTS); + } + return record; + } + + // ==================== 缺陷统计 ==================== + + /** + * 重新计算缺陷统计(行级 + 主表级),委托给对应的检验 Service + * + * @param qcType 检验类型 + * @param qcId 检验单 ID + */ + private void recalculateDefectStats(Integer qcType, Long qcId) { + List records = defectRecordMapper.selectListByQcTypeAndQcId(qcType, qcId); + if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) { + iqcService.recalculateDefectStats(qcId, records); + } else if (Objects.equals(qcType, MesQcTypeEnum.IPQC.getType())) { + ipqcService.recalculateDefectStats(qcId, records); + } else if (Objects.equals(qcType, MesQcTypeEnum.OQC.getType())) { + oqcService.recalculateDefectStats(qcId, records); + } else if (Objects.equals(qcType, MesQcTypeEnum.RQC.getType())) { + rqcService.recalculateDefectStats(qcId, records); + } else { + throw exception(QC_DEFECT_RECORD_QC_TYPE_UNSUPPORTED); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorService.java new file mode 100644 index 000000000..8a9f5cba1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.service.qc.indicator; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo.MesQcIndicatorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo.MesQcIndicatorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 质检指标 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcIndicatorService { + + /** + * 创建质检指标 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createIndicator(@Valid MesQcIndicatorSaveReqVO createReqVO); + + /** + * 更新质检指标 + * + * @param updateReqVO 更新信息 + */ + void updateIndicator(@Valid MesQcIndicatorSaveReqVO updateReqVO); + + /** + * 删除质检指标 + * + * @param id 编号 + */ + void deleteIndicator(Long id); + + /** + * 获得质检指标 + * + * @param id 编号 + * @return 质检指标 + */ + MesQcIndicatorDO getIndicator(Long id); + + /** + * 获得质检指标分页 + * + * @param pageReqVO 分页查询 + * @return 质检指标分页 + */ + PageResult getIndicatorPage(MesQcIndicatorPageReqVO pageReqVO); + + /** + * 获得质检指标列表 + * + * @return 质检指标列表 + */ + List getIndicatorList(); + + /** + * 获得质检指标列表 + * + * @param ids 编号数组 + * @return 质检指标列表 + */ + List getIndicatorList(Collection ids); + + /** + * 获得质检指标 Map + * + * @param ids 编号数组 + * @return 质检指标 Map + */ + default Map getIndicatorMap(Collection ids) { + return convertMap(getIndicatorList(ids), MesQcIndicatorDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorServiceImpl.java new file mode 100644 index 000000000..b72cdc143 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorServiceImpl.java @@ -0,0 +1,135 @@ +package cn.iocoder.yudao.module.mes.service.qc.indicator; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo.MesQcIndicatorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo.MesQcIndicatorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicator.MesQcIndicatorMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 质检指标 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcIndicatorServiceImpl implements MesQcIndicatorService { + + @Resource + private MesQcIndicatorMapper indicatorMapper; + + @Override + public Long createIndicator(MesQcIndicatorSaveReqVO createReqVO) { + // 校验相关参数 + validateIndicatorSaveData(null, createReqVO); + + // 插入 + MesQcIndicatorDO indicator = BeanUtils.toBean(createReqVO, MesQcIndicatorDO.class); + indicatorMapper.insert(indicator); + return indicator.getId(); + } + + @Override + public void updateIndicator(MesQcIndicatorSaveReqVO updateReqVO) { + // 校验存在 + validateIndicatorExists(updateReqVO.getId()); + // 校验相关参数 + validateIndicatorSaveData(updateReqVO.getId(), updateReqVO); + + // 更新 + MesQcIndicatorDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIndicatorDO.class); + indicatorMapper.updateById(updateObj); + } + + @Override + public void deleteIndicator(Long id) { + // 校验存在 + validateIndicatorExists(id); + // 删除 + indicatorMapper.deleteById(id); + } + + private void validateIndicatorSaveData(Long id, MesQcIndicatorSaveReqVO saveReqVO) { + // 校验编码唯一 + validateIndicatorCodeUnique(id, saveReqVO.getCode()); + // 校验名称唯一 + validateIndicatorNameUnique(id, saveReqVO.getName()); + // 校验结果值属性 + validateResultSpecification(saveReqVO.getResultType(), saveReqVO.getResultSpecification()); + } + + private void validateIndicatorExists(Long id) { + if (indicatorMapper.selectById(id) == null) { + throw exception(QC_INDICATOR_NOT_EXISTS); + } + } + + private void validateIndicatorCodeUnique(Long id, String code) { + MesQcIndicatorDO indicator = indicatorMapper.selectByCode(code); + if (indicator == null) { + return; + } + if (ObjUtil.notEqual(indicator.getId(), id)) { + throw exception(QC_INDICATOR_CODE_DUPLICATE); + } + } + + private void validateIndicatorNameUnique(Long id, String name) { + MesQcIndicatorDO indicator = indicatorMapper.selectByName(name); + if (indicator == null) { + return; + } + if (ObjUtil.notEqual(indicator.getId(), id)) { + throw exception(QC_INDICATOR_NAME_DUPLICATE); + } + } + + private void validateResultSpecification(Integer resultType, String resultSpecification) { + if (ObjectUtils.equalsAny(resultType, MesQcResultValueTypeEnum.FILE.getType(), + MesQcResultValueTypeEnum.DICT.getType())) { + if (StrUtil.isBlank(resultSpecification)) { + throw exception(QC_INDICATOR_RESULT_SPECIFICATION_REQUIRED); + } + } + } + + @Override + public MesQcIndicatorDO getIndicator(Long id) { + return indicatorMapper.selectById(id); + } + + @Override + public PageResult getIndicatorPage(MesQcIndicatorPageReqVO pageReqVO) { + return indicatorMapper.selectPage(pageReqVO); + } + + @Override + public List getIndicatorList() { + return indicatorMapper.selectList(); + } + + @Override + public List getIndicatorList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return indicatorMapper.selectByIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultDetailService.java new file mode 100644 index 000000000..680ab6694 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultDetailService.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.mes.service.qc.indicatorresult; + +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO; + +import java.util.List; + +/** + * MES 检验结果明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcIndicatorResultDetailService { + + /** + * 批量创建检验结果明细 + * + * @param details 明细列表 + */ + void createDetailList(List details); + + /** + * 批量新增或更新检验结果明细 + * + * @param details 明细列表 + */ + void createOrUpdateDetailList(List details); + + /** + * 根据检验结果 ID 获取明细列表 + * + * @param resultId 检验结果 ID + * @return 明细列表 + */ + List getDetailListByResultId(Long resultId); + + /** + * 根据检验结果 ID 删除所有明细 + * + * @param resultId 检验结果 ID + */ + void deleteDetailByResultId(Long resultId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultDetailServiceImpl.java new file mode 100644 index 000000000..f32af8607 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultDetailServiceImpl.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.service.qc.indicatorresult; + +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcIndicatorResultDetailMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +/** + * MES 检验结果明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcIndicatorResultDetailServiceImpl implements MesQcIndicatorResultDetailService { + + @Resource + private MesQcIndicatorResultDetailMapper detailMapper; + + @Override + public void createDetailList(List details) { + detailMapper.insertBatch(details); + } + + @Override + public void createOrUpdateDetailList(List details) { + detailMapper.insertOrUpdate(details); + } + + @Override + public List getDetailListByResultId(Long resultId) { + return detailMapper.selectListByResultId(resultId); + } + + @Override + public void deleteDetailByResultId(Long resultId) { + detailMapper.delete(new LambdaQueryWrapperX() + .eq(MesQcIndicatorResultDetailDO::getResultId, resultId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultService.java new file mode 100644 index 000000000..ea4f2c7ba --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultService.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.mes.service.qc.indicatorresult; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 检验结果 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcIndicatorResultService { + + /** + * 创建检验结果(含明细) + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createIndicatorResult(@Valid MesQcIndicatorResultSaveReqVO createReqVO); + + /** + * 更新检验结果(含明细) + * + * @param updateReqVO 更新信息 + */ + void updateIndicatorResult(@Valid MesQcIndicatorResultSaveReqVO updateReqVO); + + /** + * 删除检验结果(级联删除明细) + * + * @param id 编号 + */ + void deleteIndicatorResult(Long id); + + /** + * 获得检验结果 + * + * @param id 编号 + * @return 检验结果 + */ + MesQcIndicatorResultDO getIndicatorResult(Long id); + + /** + * 获得检验结果分页 + * + * @param pageReqVO 分页查询 + * @return 检验结果分页 + */ + PageResult getIndicatorResultPage(MesQcIndicatorResultPageReqVO pageReqVO); + + /** + * 获取检验结果明细列表 + * + * @param resultId 检验结果 ID + * @return 明细列表 + */ + List getIndicatorResultDetailListByResultId(Long resultId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java new file mode 100644 index 000000000..3791a980f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java @@ -0,0 +1,170 @@ +package cn.iocoder.yudao.module.mes.service.qc.indicatorresult; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcIndicatorResultMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; +import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 检验结果 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultService { + + @Resource + private MesQcIndicatorResultMapper resultMapper; + @Resource + private MesQcIndicatorResultDetailService resultDetailService; + + @Resource + private MesQcIndicatorService indicatorService; + @Resource + private MesQcIqcService iqcService; + @Resource + @Lazy + private MesQcIpqcService ipqcService; + @Resource + @Lazy + private MesQcOqcService oqcService; + @Resource + @Lazy + private MesQcRqcService rqcService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createIndicatorResult(MesQcIndicatorResultSaveReqVO createReqVO) { + // 1.1 根据 qcType 查询源质检单,获取 itemId + Long itemId = getItemIdFromQcDoc(createReqVO.getQcId(), createReqVO.getQcType()); + // 1.2 校验所有明细的 indicatorId 是否存在 + validateIndicatorIds(createReqVO.getItems()); + + // 2.1 插入主表 + MesQcIndicatorResultDO result = BeanUtils.toBean(createReqVO, MesQcIndicatorResultDO.class); + result.setItemId(itemId); + resultMapper.insert(result); + // 2.2 批量插入明细 + List details = BeanUtils.toBean(createReqVO.getItems(), + MesQcIndicatorResultDetailDO.class); + details.forEach(detail -> detail.setResultId(result.getId())); + resultDetailService.createDetailList(details); + return result.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateIndicatorResult(MesQcIndicatorResultSaveReqVO updateReqVO) { + // 1. 校验存在 + validateIndicatorResultExists(updateReqVO.getId()); + + // 2.1 更新主表 + MesQcIndicatorResultDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIndicatorResultDO.class); + resultMapper.updateById(updateObj); + // 2.2 批量更新明细 + List details = BeanUtils.toBean(updateReqVO.getItems(), + MesQcIndicatorResultDetailDO.class); + resultDetailService.createOrUpdateDetailList(details); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteIndicatorResult(Long id) { + // 1. 校验存在 + validateIndicatorResultExists(id); + + // 2.1 级联删除明细 + resultDetailService.deleteDetailByResultId(id); + // 2.2 删除主表 + resultMapper.deleteById(id); + } + + @Override + public MesQcIndicatorResultDO getIndicatorResult(Long id) { + return resultMapper.selectById(id); + } + + @Override + public PageResult getIndicatorResultPage(MesQcIndicatorResultPageReqVO pageReqVO) { + return resultMapper.selectPage(pageReqVO); + } + + @Override + public List getIndicatorResultDetailListByResultId(Long resultId) { + return resultDetailService.getDetailListByResultId(resultId); + } + + // ==================== 私有方法 ==================== + + private MesQcIndicatorResultDO validateIndicatorResultExists(Long id) { + MesQcIndicatorResultDO result = resultMapper.selectById(id); + if (result == null) { + throw exception(QC_RESULT_NOT_EXISTS); + } + return result; + } + + /** + * 校验所有明细的 indicatorId 是否存在 + */ + private void validateIndicatorIds(List items) { + if (CollUtil.isEmpty(items)) { + return; + } + Set indicatorIds = convertSet(items, MesQcIndicatorResultSaveReqVO.Item::getIndicatorId); + List indicators = indicatorService.getIndicatorList(indicatorIds); + if (indicators.size() != indicatorIds.size()) { + Set existIds = convertSet(indicators, MesQcIndicatorDO::getId); + indicatorIds.removeAll(existIds); + throw exception(QC_INDICATOR_NOT_EXISTS); + } + } + + /** + * 根据 qcType 查询源质检单,获取 itemId + */ + private Long getItemIdFromQcDoc(Long qcId, Integer qcType) { + if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) { + MesQcIqcDO iqc = iqcService.validateIqcExists(qcId); + return iqc.getItemId(); + } else if (Objects.equals(qcType, MesQcTypeEnum.IPQC.getType())) { + MesQcIpqcDO ipqc = ipqcService.validateIpqcExists(qcId); + return ipqc.getItemId(); + } else if (Objects.equals(qcType, MesQcTypeEnum.OQC.getType())) { + MesQcOqcDO oqc = oqcService.validateOqcExists(qcId); + return oqc.getItemId(); + } else if (Objects.equals(qcType, MesQcTypeEnum.RQC.getType())) { + MesQcRqcDO rqc = rqcService.validateRqcExists(qcId); + return rqc.getItemId(); + } + throw new IllegalArgumentException("暂不支持 qcType=" + qcType); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineService.java new file mode 100644 index 000000000..df2d09e49 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineService.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.mes.service.qc.ipqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; + +import java.util.List; + +/** + * MES 过程检验单行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcIpqcLineService { + + /** + * 校验过程检验行存在 + * + * @param id 编号 + * @return 过程检验行 + */ + MesQcIpqcLineDO validateIpqcLineExists(Long id); + + /** + * 获得过程检验行 + * + * @param id 编号 + * @return 过程检验行 + */ + MesQcIpqcLineDO getIpqcLine(Long id); + + /** + * 获得过程检验行分页 + * + * @param pageReqVO 分页查询 + * @return 过程检验行分页 + */ + PageResult getIpqcLinePage(MesQcIpqcLinePageReqVO pageReqVO); + + /** + * 从模板指标自动生成检验行 + * + * @param ipqcId 过程检验单 ID + * @param templateId 模板 ID + */ + void createLinesFromTemplate(Long ipqcId, Long templateId); + + /** + * 根据缺陷记录重新计算行级缺陷统计 + * + * @param ipqcId 过程检验单 ID + * @param records 缺陷记录列表 + */ + void recalculateLineDefectStats(Long ipqcId, List records); + + /** + * 根据过程检验单 ID 获取所有行 + * + * @param ipqcId 过程检验单 ID + * @return 行列表 + */ + List getIpqcLineListByIpqcId(Long ipqcId); + + /** + * 根据过程检验单 ID 级联删除所有行 + * + * @param ipqcId 过程检验单 ID + */ + void deleteListByIpqcId(Long ipqcId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineServiceImpl.java new file mode 100644 index 000000000..f3cff4ef1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineServiceImpl.java @@ -0,0 +1,130 @@ +package cn.iocoder.yudao.module.mes.service.qc.ipqc; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.line.MesQcIpqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcLineMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +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.*; + +/** + * MES 过程检验单行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcIpqcLineServiceImpl implements MesQcIpqcLineService { + + @Resource + private MesQcIpqcLineMapper ipqcLineMapper; + @Resource + private MesQcTemplateIndicatorMapper templateIndicatorMapper; + + @Resource + private MesQcIndicatorService indicatorService; + + @Override + public MesQcIpqcLineDO validateIpqcLineExists(Long id) { + MesQcIpqcLineDO line = ipqcLineMapper.selectById(id); + if (line == null) { + throw exception(QC_IPQC_LINE_NOT_EXISTS); + } + return line; + } + + @Override + public MesQcIpqcLineDO getIpqcLine(Long id) { + return ipqcLineMapper.selectById(id); + } + + @Override + public PageResult getIpqcLinePage(MesQcIpqcLinePageReqVO pageReqVO) { + return ipqcLineMapper.selectPage(pageReqVO); + } + + @Override + public void createLinesFromTemplate(Long ipqcId, Long templateId) { + List templateIndicators = templateIndicatorMapper.selectListByTemplateId(templateId); + if (CollUtil.isEmpty(templateIndicators)) { + return; + } + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(templateIndicators, MesQcTemplateIndicatorDO::getIndicatorId)); + List lines = convertList(templateIndicators, templateIndicator -> { + MesQcIndicatorDO indicator = indicatorMap.get(templateIndicator.getIndicatorId()); + return new MesQcIpqcLineDO() + .setIpqcId(ipqcId).setIndicatorId(templateIndicator.getIndicatorId()) + .setTool(indicator != null ? indicator.getTool() : null) + .setCheckMethod(templateIndicator.getCheckMethod()) + .setStandardValue(templateIndicator.getStandardValue()).setUnitMeasureId(templateIndicator.getUnitMeasureId()) + .setMaxThreshold(templateIndicator.getThresholdMax()).setMinThreshold(templateIndicator.getThresholdMin()) + .setCriticalQuantity(0).setMajorQuantity(0).setMinorQuantity(0); + }); + ipqcLineMapper.insertBatch(lines); + } + + @Override + public void recalculateLineDefectStats(Long ipqcId, List records) { + List lines = ipqcLineMapper.selectListByIpqcId(ipqcId); + if (CollUtil.isEmpty(lines)) { + return; + } + List updateLines = new ArrayList<>(lines.size()); + for (MesQcIpqcLineDO line : lines) { + int critical = 0; + int major = 0; + int minor = 0; + for (MesQcDefectRecordDO record : records) { + if (ObjUtil.notEqual(record.getLineId(), line.getId())) { + continue; + } + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + critical += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + major += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + minor += quantity; + } else { + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); + } + } + updateLines.add(new MesQcIpqcLineDO().setId(line.getId()) + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor)); + } + for (MesQcIpqcLineDO updateLine : updateLines) { + ipqcLineMapper.updateById(updateLine); + } + } + + @Override + public List getIpqcLineListByIpqcId(Long ipqcId) { + return ipqcLineMapper.selectListByIpqcId(ipqcId); + } + + @Override + public void deleteListByIpqcId(Long ipqcId) { + ipqcLineMapper.deleteByIpqcId(ipqcId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcService.java new file mode 100644 index 000000000..1de46ffd3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcService.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.mes.service.qc.ipqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 过程检验单(IPQC) Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcIpqcService { + + /** + * 创建过程检验单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createIpqc(@Valid MesQcIpqcSaveReqVO createReqVO); + + /** + * 更新过程检验单 + * + * @param updateReqVO 更新信息 + */ + void updateIpqc(@Valid MesQcIpqcSaveReqVO updateReqVO); + + /** + * 完成过程检验单 + * + * @param id 编号 + */ + void finishIpqc(Long id); + + /** + * 删除过程检验单 + * + * @param id 编号 + */ + void deleteIpqc(Long id); + + /** + * 获得过程检验单 + * + * @param id 编号 + * @return 过程检验单 + */ + MesQcIpqcDO getIpqc(Long id); + + /** + * 获得过程检验单分页 + * + * @param pageReqVO 分页查询 + * @return 过程检验单分页 + */ + PageResult getIpqcPage(MesQcIpqcPageReqVO pageReqVO); + + /** + * 校验过程检验单存在 + * + * @param id 编号 + * @return 过程检验单 + */ + MesQcIpqcDO validateIpqcExists(Long id); + + /** + * 根据缺陷记录重新计算主表的缺陷统计(含行级下沉) + * + * @param ipqcId 过程检验单 ID + * @param records 缺陷记录列表 + */ + void recalculateDefectStats(Long ipqcId, List records); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java new file mode 100644 index 000000000..98cc65586 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java @@ -0,0 +1,326 @@ +package cn.iocoder.yudao.module.mes.service.qc.ipqc; + +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 过程检验单(IPQC) Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcIpqcServiceImpl implements MesQcIpqcService { + + + @Resource + private MesQcIpqcMapper ipqcMapper; + + @Resource + private MesQcTemplateItemService templateItemService; + @Resource + private MesQcIpqcLineService ipqcLineService; + @Resource + @Lazy + private MesProWorkOrderService workOrderService; + @Resource + @Lazy + private MesMdWorkstationService workstationService; + @Resource + @Lazy + private MesMdItemService itemService; + @Resource + @Lazy + private MesQcDefectRecordService defectRecordService; + @Resource + @Lazy + private MesProRouteProductService routeProductService; + @Resource + @Lazy + private MesProRouteProcessService routeProcessService; + + @Resource + private AdminUserApi adminUserApi; + @Resource + @Lazy + private MesProFeedbackService feedbackService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createIpqc(MesQcIpqcSaveReqVO createReqVO) { + // 1.1 校验数据 + MesMdWorkstationDO workstation = validateIpqcSaveData(createReqVO); + // 1.2 校验工单存在 + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); + // 1.3 根据产品 + 检验类型自动匹配模板 + MesQcTemplateItemDO templateItem = templateItemService.getRequiredTemplateByItemIdAndType( + workOrder.getProductId(), MesQcTypeEnum.IPQC.getType()); + Long templateId = templateItem.getTemplateId(); + // 1.4 获取来源单据编号 + String sourceDocCode = validateAndGetSourceDocCode( + createReqVO.getSourceDocType(), createReqVO.getSourceDocId()); + + // 2. 插入主表 + MesQcIpqcDO ipqc = BeanUtils.toBean(createReqVO, MesQcIpqcDO.class) + .setItemId(workOrder.getProductId()) + .setProcessId(getProcessId(workOrder.getProductId(), workstation.getProcessId())) + .setTemplateId(templateId) + .setSourceDocCode(sourceDocCode) + .setStatus(MesQcStatusEnum.DRAFT.getStatus()); + ipqcMapper.insert(ipqc); + + // 3. 从模板指标自动生成检验行 + ipqcLineService.createLinesFromTemplate(ipqc.getId(), templateId); + return ipqc.getId(); + } + + @Override + public void updateIpqc(MesQcIpqcSaveReqVO updateReqVO) { + // 1.1 校验存在 + 草稿状态 + validateIpqcStatusPrepare(updateReqVO.getId()); + // 1.2 校验数据 + MesMdWorkstationDO workstation = validateIpqcSaveData(updateReqVO); + + // 2. 更新主表 + MesQcIpqcDO existIpqc = validateIpqcExists(updateReqVO.getId()); + MesQcIpqcDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIpqcDO.class); + updateObj.setSourceDocType(null).setSourceDocId(null).setSourceLineId(null); // 不允许修改来源单据 + updateObj.setTemplateId(null); // 不允许修改模板 + updateObj.setItemId(null); // 不允许修改物料 + updateObj.setWorkOrderId(null); // 不允许修改工单 + updateObj.setProcessId(getProcessId(existIpqc.getItemId(), workstation.getProcessId())); + ipqcMapper.updateById(updateObj); + } + + private MesMdWorkstationDO validateIpqcSaveData(MesQcIpqcSaveReqVO reqVO) { + // 校验编号唯一 + validateIpqcCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验工位、检测人员存在 + MesMdWorkstationDO workstation = workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + adminUserApi.validateUser(reqVO.getInspectorUserId()); + return workstation; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishIpqc(Long id) { + // 1.1 校验存在 + 草稿状态 + MesQcIpqcDO ipqc = validateIpqcStatusPrepare(id); + // 1.2 校验检测结论必填 + if (ipqc.getCheckResult() == null) { + throw exception(QC_IPQC_CHECK_RESULT_EMPTY); + } + + // 2. 更新状态为已完成 + ipqcMapper.updateById(new MesQcIpqcDO() + .setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus())); + + // 3. 回写来源单据 + writeBackSourceDoc(ipqc); + } + + /** + * 回写来源单据(IPQC 完成后) + * + *

当来源为报工时,拆分待检产出行、完成产出入库、回写报工状态和任务/工单进度 + * + * @param ipqc 过程检验单 + */ + private void writeBackSourceDoc(MesQcIpqcDO ipqc) { + if (ipqc.getSourceDocType() == null) { + return; + } + if (ipqc.getSourceDocId() == null) { + throw new IllegalArgumentException( + "IPQC 单[" + ipqc.getId() + "] sourceDocType 非空但 sourceDocId 为空"); + } + + if (Objects.equals(ipqc.getSourceDocType(), MesBizTypeConstants.PRO_FEEDBACK)) { + feedbackService.updateProFeedbackWhenIpqcFinish(ipqc.getSourceDocId(), + ObjectUtil.defaultIfNull(ipqc.getQualifiedQuantity(), BigDecimal.ZERO), + ObjectUtil.defaultIfNull(ipqc.getUnqualifiedQuantity(), BigDecimal.ZERO), + ObjectUtil.defaultIfNull(ipqc.getLaborScrapQuantity(), BigDecimal.ZERO), + ObjectUtil.defaultIfNull(ipqc.getMaterialScrapQuantity(), BigDecimal.ZERO), + ObjectUtil.defaultIfNull(ipqc.getOtherScrapQuantity(), BigDecimal.ZERO)); + } else { + throw new IllegalArgumentException( + "IPQC 单[" + ipqc.getId() + "] sourceDocType=" + ipqc.getSourceDocType() + " 无法识别,无法回写来源单据"); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteIpqc(Long id) { + // 1. 校验存在 + 草稿状态 + validateIpqcStatusPrepare(id); + + // 2.1 删除主表 + ipqcMapper.deleteById(id); + // 2.2 级联删除行 + ipqcLineService.deleteListByIpqcId(id); + // 2.3 级联删除缺陷记录 + defectRecordService.deleteListByQcTypeAndQcId(MesQcTypeEnum.IPQC.getType(), id); + } + + @Override + public MesQcIpqcDO validateIpqcExists(Long id) { + MesQcIpqcDO ipqc = ipqcMapper.selectById(id); + if (ipqc == null) { + throw exception(QC_IPQC_NOT_EXISTS); + } + return ipqc; + } + + /** + * 校验过程检验单存在且为草稿状态 + * + * @param id 过程检验单 ID + * @return 过程检验单 + */ + private MesQcIpqcDO validateIpqcStatusPrepare(Long id) { + MesQcIpqcDO ipqc = validateIpqcExists(id); + if (ObjUtil.notEqual(ipqc.getStatus(), MesQcStatusEnum.DRAFT.getStatus())) { + throw exception(QC_IPQC_NOT_PREPARE); + } + return ipqc; + } + + private void validateIpqcCodeUnique(Long id, String code) { + MesQcIpqcDO ipqc = ipqcMapper.selectByCode(code); + if (ipqc == null) { + return; + } + if (ObjUtil.notEqual(ipqc.getId(), id)) { + throw exception(QC_IPQC_CODE_DUPLICATE); + } + } + + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId) { + if (sourceDocType == null || sourceDocId == null) { + return null; + } + if (Objects.equals(sourceDocType, MesBizTypeConstants.PRO_FEEDBACK)) { + MesProFeedbackDO feedback = feedbackService.getFeedback(sourceDocId); + return feedback != null ? feedback.getCode() : null; + } + return null; + } + + /** + * 推导工序 ID + * + *

通过产品 → 工艺路线产品 → 工艺路线 → 校验工位工序是否在该路线中 + *

如果工位的工序在路线中,则返回该 processId;否则返回 null + * + * @param productId 产品 ID(工单产品) + * @param workstationProcessId 工位关联的工序 ID + * @return 推导出的工序 ID,无法推导时返回 null + */ + private Long getProcessId(Long productId, Long workstationProcessId) { + if (productId == null || workstationProcessId == null) { + return null; + } + // 1. 产品 → 工艺路线 + MesProRouteProductDO routeProduct = routeProductService.getRouteProductByItemId(productId); + if (routeProduct == null) { + return null; + } + // 2. 校验工位的工序是否在该路线中 + if (routeProcessService.getRouteProcessByRouteIdAndProcessId( + routeProduct.getRouteId(), workstationProcessId) == null) { + return null; + } + return workstationProcessId; + } + + @Override + public MesQcIpqcDO getIpqc(Long id) { + return ipqcMapper.selectById(id); + } + + @Override + public PageResult getIpqcPage(MesQcIpqcPageReqVO pageReqVO) { + return ipqcMapper.selectPage(pageReqVO); + } + + @Override + public void recalculateDefectStats(Long ipqcId, List records) { + MesQcIpqcDO ipqc = validateIpqcExists(ipqcId); + // 1. 行级缺陷统计 + ipqcLineService.recalculateLineDefectStats(ipqcId, records); + + // 2.1 汇总主表的缺陷数量 + int totalCritical = 0; + int totalMajor = 0; + int totalMinor = 0; + for (MesQcDefectRecordDO record : records) { + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + totalCritical += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + totalMajor += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + totalMinor += quantity; + } else { + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); + } + } + // 2.2 计算缺陷率 + BigDecimal criticalRate = BigDecimal.ZERO; + BigDecimal majorRate = BigDecimal.ZERO; + BigDecimal minorRate = BigDecimal.ZERO; + if (ipqc.getCheckQuantity() != null && ipqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + BigDecimal checkQty = ipqc.getCheckQuantity(); + criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + } + // 2.3 更新主表 + MesQcIpqcDO updateIpqc = new MesQcIpqcDO().setId(ipqcId) + .setCriticalQuantity(totalCritical).setMajorQuantity(totalMajor).setMinorQuantity(totalMinor) + .setCriticalRate(criticalRate).setMajorRate(majorRate).setMinorRate(minorRate); + ipqcMapper.updateById(updateIpqc); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineService.java new file mode 100644 index 000000000..544d46bcc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineService.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.service.qc.iqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcLineDO; + +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; + +import java.util.List; + +/** + * MES 来料检验单行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcIqcLineService { + + /** + * 校验来料检验行存在 + * + * @param id 编号 + * @return 来料检验行 + */ + MesQcIqcLineDO validateIqcLineExists(Long id); + + /** + * 获得来料检验行 + * + * @param id 编号 + * @return 来料检验行 + */ + MesQcIqcLineDO getIqcLine(Long id); + + /** + * 获得来料检验行分页 + * + * @param pageReqVO 分页查询 + * @return 来料检验行分页 + */ + PageResult getIqcLinePage(MesQcIqcLinePageReqVO pageReqVO); + + /** + * 从模板指标自动生成检验行 + * + * @param iqcId 来料检验单 ID + * @param templateId 模板 ID + */ + void createLinesFromTemplate(Long iqcId, Long templateId); + + /** + * 根据缺陷记录重新计算各行的缺陷统计数量 + * + * @param iqcId 来料检验单 ID + * @param records 缺陷记录列表 + */ + void recalculateLineDefectStats(Long iqcId, List records); + + /** + * 根据来料检验单 ID 获取所有行 + * + * @param iqcId 来料检验单 ID + * @return 行列表 + */ + List getIqcLineListByIqcId(Long iqcId); + + /** + * 根据来料检验单 ID 级联删除所有行 + * + * @param iqcId 来料检验单 ID + */ + void deleteListByIqcId(Long iqcId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineServiceImpl.java new file mode 100644 index 000000000..268f9b103 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineServiceImpl.java @@ -0,0 +1,130 @@ +package cn.iocoder.yudao.module.mes.service.qc.iqc; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.iqc.MesQcIqcLineMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +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.*; + +/** + * MES 来料检验单行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcIqcLineServiceImpl implements MesQcIqcLineService { + + @Resource + private MesQcIqcLineMapper iqcLineMapper; + @Resource + private MesQcTemplateIndicatorMapper templateIndicatorMapper; + + @Resource + private MesQcIndicatorService indicatorService; + + @Override + public MesQcIqcLineDO validateIqcLineExists(Long id) { + MesQcIqcLineDO line = iqcLineMapper.selectById(id); + if (line == null) { + throw exception(QC_IQC_LINE_NOT_EXISTS); + } + return line; + } + + @Override + public MesQcIqcLineDO getIqcLine(Long id) { + return iqcLineMapper.selectById(id); + } + + @Override + public PageResult getIqcLinePage(MesQcIqcLinePageReqVO pageReqVO) { + return iqcLineMapper.selectPage(pageReqVO); + } + + @Override + public void createLinesFromTemplate(Long iqcId, Long templateId) { + List templateIndicators = templateIndicatorMapper.selectListByTemplateId(templateId); + if (CollUtil.isEmpty(templateIndicators)) { + return; + } + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(templateIndicators, MesQcTemplateIndicatorDO::getIndicatorId)); + List lines = convertList(templateIndicators, templateIndicator -> { + MesQcIndicatorDO indicator = indicatorMap.get(templateIndicator.getIndicatorId()); + return new MesQcIqcLineDO() + .setIqcId(iqcId).setIndicatorId(templateIndicator.getIndicatorId()) + .setTool(indicator != null ? indicator.getTool() : null) + .setCheckMethod(templateIndicator.getCheckMethod()) + .setStandardValue(templateIndicator.getStandardValue()).setUnitMeasureId(templateIndicator.getUnitMeasureId()) + .setMaxThreshold(templateIndicator.getThresholdMax()).setMinThreshold(templateIndicator.getThresholdMin()) + .setCriticalQuantity(0).setMajorQuantity(0).setMinorQuantity(0); + }); + iqcLineMapper.insertBatch(lines); + } + + @Override + public void recalculateLineDefectStats(Long iqcId, List records) { + List lines = iqcLineMapper.selectListByIqcId(iqcId); + if (CollUtil.isEmpty(lines)) { + return; + } + List updateLines = new ArrayList<>(lines.size()); + for (MesQcIqcLineDO line : lines) { + int critical = 0; + int major = 0; + int minor = 0; + for (MesQcDefectRecordDO record : records) { + if (ObjUtil.notEqual(record.getLineId(), line.getId())) { + continue; + } + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + critical += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + major += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + minor += quantity; + } else { + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); + } + } + updateLines.add(new MesQcIqcLineDO().setId(line.getId()) + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor)); + } + for (MesQcIqcLineDO updateLine : updateLines) { + iqcLineMapper.updateById(updateLine); + } + } + + @Override + public List getIqcLineListByIqcId(Long iqcId) { + return iqcLineMapper.selectListByIqcId(iqcId); + } + + @Override + public void deleteListByIqcId(Long iqcId) { + iqcLineMapper.deleteByIqcId(iqcId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcService.java new file mode 100644 index 000000000..49de3f234 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcService.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.service.qc.iqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * MES 来料检验单(IQC) Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcIqcService { + + /** + * 创建来料检验单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createIqc(@Valid MesQcIqcSaveReqVO createReqVO); + + /** + * 更新来料检验单 + * + * @param updateReqVO 更新信息 + */ + void updateIqc(@Valid MesQcIqcSaveReqVO updateReqVO); + + /** + * 完成来料检验单 + * + * @param id 编号 + */ + void finishIqc(Long id); + + /** + * 删除来料检验单 + * + * @param id 编号 + */ + void deleteIqc(Long id); + + /** + * 校验来料检验单存在 + * + * @param id 编号 + * @return 来料检验单 + */ + MesQcIqcDO validateIqcExists(Long id); + + /** + * 获得来料检验单 + * + * @param id 编号 + * @return 来料检验单 + */ + MesQcIqcDO getIqc(Long id); + + /** + * 获得来料检验单分页 + * + * @param pageReqVO 分页查询 + * @return 来料检验单分页 + */ + PageResult getIqcPage(MesQcIqcPageReqVO pageReqVO); + + /** + * 根据缺陷记录重新计算主表的缺陷统计(含行级下沉) + * + * @param iqcId 来料检验单 ID + * @param records 缺陷记录列表 + */ + void recalculateDefectStats(Long iqcId, List records); + + /** + * 批量获取来料检验单 Map + * + * @param ids 编号集合 + * @return 来料检验单 Map + */ + Map getIqcMap(Collection ids); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java new file mode 100644 index 000000000..3efd44b8c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java @@ -0,0 +1,299 @@ +package cn.iocoder.yudao.module.mes.service.qc.iqc; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.iqc.MesQcIqcMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 来料检验单(IQC) Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcIqcServiceImpl implements MesQcIqcService { + + @Resource + private MesQcIqcMapper iqcMapper; + + @Resource + private MesQcTemplateItemService templateItemService; + @Resource + private MesQcIqcLineService iqcLineService; + @Resource + private MesQcDefectRecordService defectRecordService; + @Resource + private MesWmArrivalNoticeService arrivalNoticeService; + @Resource + private MesWmOutsourceReceiptService outsourceReceiptService; + @Resource + private MesMdVendorService vendorService; + @Resource + private MesMdItemService itemService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createIqc(MesQcIqcSaveReqVO createReqVO) { + // 1.1 校验数据 + validateIqcSaveData(createReqVO); + // 1.2 校验来源单据参数,并验证数据存在 + String sourceDocCode = validateAndGetSourceDocCode( + createReqVO.getSourceDocType(), createReqVO.getSourceDocId(), createReqVO.getSourceLineId()); + // 1.3 通过 itemId + IQC 类型自动查找模板 + MesQcTemplateItemDO templateItem = templateItemService.getRequiredTemplateByItemIdAndType( + createReqVO.getItemId(), MesQcTypeEnum.IQC.getType()); + Long templateId = templateItem.getTemplateId(); + + // 2. 插入主表 + MesQcIqcDO iqc = BeanUtils.toBean(createReqVO, MesQcIqcDO.class) + .setTemplateId(templateId) + .setCheckQuantity(createReqVO.getQualifiedQuantity().add(createReqVO.getUnqualifiedQuantity())) + .setSourceDocCode(sourceDocCode) + .setStatus(MesQcStatusEnum.DRAFT.getStatus()); + iqcMapper.insert(iqc); + + // 3. 从模板指标自动生成检验行 + iqcLineService.createLinesFromTemplate(iqc.getId(), templateId); + return iqc.getId(); + } + + @Override + public void updateIqc(MesQcIqcSaveReqVO updateReqVO) { + // 1.1 校验存在 + 草稿状态 + validateIqcStatusPrepare(updateReqVO.getId()); + // 1.2 校验数据 + validateIqcSaveData(updateReqVO); + + // 2. 更新主表 + MesQcIqcDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIqcDO.class); + updateObj.setSourceDocType(null).setSourceDocId(null).setSourceLineId(null); // 不允许修改来源单据 + updateObj.setTemplateId(null); // 不允许修改模板 + updateObj.setItemId(null); // 不允许修改物料 + updateObj.setCheckQuantity(updateReqVO.getQualifiedQuantity().add(updateReqVO.getUnqualifiedQuantity())); + iqcMapper.updateById(updateObj); + } + + private void validateIqcSaveData(MesQcIqcSaveReqVO reqVO) { + // 校验编号唯一 + validateIqcCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验供应商、物料、检测人员存在 + vendorService.validateVendorExists(reqVO.getVendorId()); + itemService.validateItemExists(reqVO.getItemId()); + adminUserApi.validateUser(reqVO.getInspectorUserId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishIqc(Long id) { + // 1.1 校验存在 + 草稿状态 + MesQcIqcDO iqc = validateIqcStatusPrepare(id); + if (iqc.getCheckResult() == null) { + throw exception(QC_IQC_CHECK_RESULT_EMPTY); + } + + // 2. 更新状态为已完成 + MesQcIqcDO updateObj = new MesQcIqcDO() + .setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()); + iqcMapper.updateById(updateObj); + + // 3. 回写来源单据 + writeBackSourceDoc(iqc); + } + + /** + * 回写来源单据(IQC 完成后) + * + * @param iqc 来料检验单 + */ + private void writeBackSourceDoc(MesQcIqcDO iqc) { + // 校验:sourceDocType 非空时,lineId 和 docId 必须非空,否则为脏数据 + if (iqc.getSourceDocType() == null) { + return; + } + if (ObjectUtil.hasNull(iqc.getSourceLineId(), iqc.getSourceDocId())) { + throw new IllegalArgumentException( + "IQC 单[" + iqc.getId() + "] sourceDocType 非空但 sourceLineId 或 sourceDocId 为空"); + } + + // 根据不同的来源单据类型,回写不同的单据 + if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_ARRIVAL_NOTICE)) { + arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(iqc.getSourceDocId(), iqc.getSourceLineId(), + iqc.getId(), iqc.getQualifiedQuantity()); + } else if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_OUTSOURCE_RECPT)) { + outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish(iqc.getSourceDocId(), iqc.getSourceLineId(), + iqc.getId(), iqc.getQualifiedQuantity(), iqc.getUnqualifiedQuantity()); + } else { + throw new IllegalArgumentException( + "IQC 单[" + iqc.getId() + "] sourceDocType=" + iqc.getSourceDocType() + " 无法识别,无法回写来源单据"); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteIqc(Long id) { + // 1. 校验存在 + 草稿状态 + validateIqcStatusPrepare(id); + + // 2.1 删除主表 + iqcMapper.deleteById(id); + // 2.2 级联删除行 + iqcLineService.deleteListByIqcId(id); + // 2.3 级联删除缺陷记录 + defectRecordService.deleteListByQcTypeAndQcId(MesQcTypeEnum.IQC.getType(), id); + } + + @Override + public MesQcIqcDO validateIqcExists(Long id) { + MesQcIqcDO iqc = iqcMapper.selectById(id); + if (iqc == null) { + throw exception(QC_IQC_NOT_EXISTS); + } + return iqc; + } + + /** + * 校验来料检验单存在且为草稿状态 + * + * @param id 来料检验单 ID + * @return 来料检验单 + */ + private MesQcIqcDO validateIqcStatusPrepare(Long id) { + MesQcIqcDO iqc = validateIqcExists(id); + if (ObjUtil.notEqual(iqc.getStatus(), MesQcStatusEnum.DRAFT.getStatus())) { + throw exception(QC_IQC_NOT_PREPARE); + } + return iqc; + } + + private void validateIqcCodeUnique(Long id, String code) { + MesQcIqcDO iqc = iqcMapper.selectByCode(code); + if (iqc == null) { + return; + } + if (ObjUtil.notEqual(iqc.getId(), id)) { + throw exception(QC_IQC_CODE_DUPLICATE); + } + } + + /** + * 校验来源单据参数,并验证数据存在 + * + * @param sourceDocType 来源单据类型 + * @param sourceDocId 来源单据 ID + * @param sourceLineId 来源单据行 ID + */ + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId, Long sourceLineId) { + if (sourceDocType == null) { + return null; + } + if (ObjUtil.hasNull(sourceDocId, sourceLineId)) { + throw exception(QC_IQC_SOURCE_DOC_PARAMS_MISSING); + } + // 根据来源单据类型,校验数据存在且匹配 + if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_ARRIVAL_NOTICE)) { + arrivalNoticeService.validateArrivalNoticeAndLineExists(sourceDocId, sourceLineId); + return arrivalNoticeService.getArrivalNotice(sourceDocId).getCode(); + } else if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_OUTSOURCE_RECPT)) { + outsourceReceiptService.validateOutsourceReceiptAndLineExists(sourceDocId, sourceLineId); + return outsourceReceiptService.getOutsourceReceipt(sourceDocId).getCode(); + } + return null; + } + + @Override + public MesQcIqcDO getIqc(Long id) { + return iqcMapper.selectById(id); + } + + @Override + public PageResult getIqcPage(MesQcIqcPageReqVO pageReqVO) { + return iqcMapper.selectPage(pageReqVO); + } + + @Override + public void recalculateDefectStats(Long iqcId, List records) { + MesQcIqcDO iqc = validateIqcExists(iqcId); + // 1. 行级缺陷统计 + iqcLineService.recalculateLineDefectStats(iqcId, records); + + // 2.1 汇总主表的缺陷数量 + int totalCritical = 0; + int totalMajor = 0; + int totalMinor = 0; + for (MesQcDefectRecordDO record : records) { + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + totalCritical += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + totalMajor += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + totalMinor += quantity; + } else { + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); + } + } + // 2.2 计算缺陷率 + BigDecimal criticalRate = BigDecimal.ZERO; + BigDecimal majorRate = BigDecimal.ZERO; + BigDecimal minorRate = BigDecimal.ZERO; + if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + BigDecimal checkQty = iqc.getCheckQuantity(); + criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + } + // 2.3 更新主表 + MesQcIqcDO updateIqc = new MesQcIqcDO().setId(iqcId) + .setCriticalQuantity(totalCritical).setMajorQuantity(totalMajor).setMinorQuantity(totalMinor) + .setCriticalRate(criticalRate).setMajorRate(majorRate).setMinorRate(minorRate); + iqcMapper.updateById(updateIqc); + } + + @Override + public Map getIqcMap(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyMap(); + } + List list = iqcMapper.selectByIds(ids); + return convertMap(list, MesQcIqcDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineService.java new file mode 100644 index 000000000..1f8fbb2b4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineService.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.mes.service.qc.oqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.line.MesQcOqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcLineDO; + +import java.util.List; + +/** + * MES 出货检验单行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcOqcLineService { + + /** + * 获得出货检验行 + * + * @param id 编号 + * @return 出货检验行 + */ + MesQcOqcLineDO getOqcLine(Long id); + + /** + * 获得出货检验行分页 + * + * @param pageReqVO 分页查询 + * @return 出货检验行分页 + */ + PageResult getOqcLinePage(MesQcOqcLinePageReqVO pageReqVO); + + /** + * 根据出货检验单 ID 查询所有行 + * + * @param oqcId 出货检验单 ID + * @return 行列表 + */ + List getOqcLineListByOqcId(Long oqcId); + + /** + * 从模板指标自动生成检验行 + * + * @param oqcId 出货检验单 ID + * @param templateId 模板 ID + */ + void createLinesFromTemplate(Long oqcId, Long templateId); + + /** + * 根据出货检验单 ID 级联删除所有行 + * + * @param oqcId 出货检验单 ID + */ + void deleteByOqcId(Long oqcId); + + /** + * 校验出货检验行存在 + * + * @param id 编号 + * @return 出货检验行 + */ + MesQcOqcLineDO validateOqcLineExists(Long id); + + /** + * 根据缺陷记录重新计算行级缺陷统计 + * + * @param oqcId 出货检验单 ID + * @param records 缺陷记录列表 + */ + void recalculateLineDefectStats(Long oqcId, List records); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineServiceImpl.java new file mode 100644 index 000000000..e4f02ffe4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineServiceImpl.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.mes.service.qc.oqc; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.line.MesQcOqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcLineMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +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.*; + +/** + * MES 出货检验单行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcOqcLineServiceImpl implements MesQcOqcLineService { + + @Resource + private MesQcOqcLineMapper oqcLineMapper; + @Resource + private MesQcTemplateIndicatorMapper templateIndicatorMapper; + @Resource + private MesQcIndicatorService indicatorService; + + @Override + public MesQcOqcLineDO validateOqcLineExists(Long id) { + MesQcOqcLineDO line = oqcLineMapper.selectById(id); + if (line == null) { + throw exception(QC_OQC_LINE_NOT_EXISTS); + } + return line; + } + + @Override + public MesQcOqcLineDO getOqcLine(Long id) { + return oqcLineMapper.selectById(id); + } + + @Override + public PageResult getOqcLinePage(MesQcOqcLinePageReqVO pageReqVO) { + return oqcLineMapper.selectPage(pageReqVO); + } + + @Override + public void createLinesFromTemplate(Long oqcId, Long templateId) { + List templateIndicators = templateIndicatorMapper.selectListByTemplateId(templateId); + if (CollUtil.isEmpty(templateIndicators)) { + return; + } + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(templateIndicators, MesQcTemplateIndicatorDO::getIndicatorId)); + List lines = convertList(templateIndicators, templateIndicator -> { + MesQcIndicatorDO indicator = indicatorMap.get(templateIndicator.getIndicatorId()); + return new MesQcOqcLineDO() + .setOqcId(oqcId).setIndicatorId(templateIndicator.getIndicatorId()) + .setTool(indicator != null ? indicator.getTool() : null) + .setCheckMethod(templateIndicator.getCheckMethod()) + .setStandardValue(templateIndicator.getStandardValue()).setUnitMeasureId(templateIndicator.getUnitMeasureId()) + .setMaxThreshold(templateIndicator.getThresholdMax()).setMinThreshold(templateIndicator.getThresholdMin()) + .setCriticalQuantity(0).setMajorQuantity(0).setMinorQuantity(0); + }); + oqcLineMapper.insertBatch(lines); + } + + @Override + public void recalculateLineDefectStats(Long oqcId, List records) { + List lines = oqcLineMapper.selectListByOqcId(oqcId); + if (CollUtil.isEmpty(lines)) { + return; + } + List updateLines = new ArrayList<>(lines.size()); + for (MesQcOqcLineDO line : lines) { + int critical = 0, major = 0, minor = 0; + for (MesQcDefectRecordDO record : records) { + if (ObjUtil.notEqual(record.getLineId(), line.getId())) { + continue; + } + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + critical += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + major += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + minor += quantity; + } else { + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); + } + } + updateLines.add(new MesQcOqcLineDO().setId(line.getId()) + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor)); + } + for (MesQcOqcLineDO updateLine : updateLines) { + oqcLineMapper.updateById(updateLine); + } + } + + @Override + public List getOqcLineListByOqcId(Long oqcId) { + return oqcLineMapper.selectListByOqcId(oqcId); + } + + @Override + public void deleteByOqcId(Long oqcId) { + oqcLineMapper.deleteByOqcId(oqcId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcService.java new file mode 100644 index 000000000..cb3632412 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcService.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.mes.service.qc.oqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 出货检验单(OQC) Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcOqcService { + + /** + * 创建出货检验单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOqc(@Valid MesQcOqcSaveReqVO createReqVO); + + /** + * 更新出货检验单 + * + * @param updateReqVO 更新信息 + */ + void updateOqc(@Valid MesQcOqcSaveReqVO updateReqVO); + + /** + * 完成出货检验单 + * + * @param id 编号 + */ + void finishOqc(Long id); + + /** + * 删除出货检验单 + * + * @param id 编号 + */ + void deleteOqc(Long id); + + /** + * 校验出货检验单存在 + * + * @param id 编号 + * @return 出货检验单 + */ + MesQcOqcDO validateOqcExists(Long id); + + /** + * 获得出货检验单 + * + * @param id 编号 + * @return 出货检验单 + */ + MesQcOqcDO getOqc(Long id); + + /** + * 获得出货检验单分页 + * + * @param pageReqVO 分页查询 + * @return 出货检验单分页 + */ + PageResult getOqcPage(MesQcOqcPageReqVO pageReqVO); + + /** + * 根据缺陷记录重新计算主表的缺陷统计(含行级下沉) + * + * @param oqcId 出货检验单 ID + * @param records 缺陷记录列表 + */ + void recalculateDefectStats(Long oqcId, List records); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java new file mode 100644 index 000000000..6e276aab4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java @@ -0,0 +1,283 @@ +package cn.iocoder.yudao.module.mes.service.qc.oqc; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService; +import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 出货检验单(OQC) Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcOqcServiceImpl implements MesQcOqcService { + + @Resource + private MesQcOqcMapper oqcMapper; + @Resource + private MesQcTemplateItemService templateItemService; + @Resource + private MesQcOqcLineService oqcLineService; + @Resource + @Lazy + private MesQcDefectRecordService defectRecordService; + @Resource + @Lazy + private MesMdClientService clientService; + @Resource + @Lazy + private MesMdItemService itemService; + @Resource + @Lazy + private MesWmProductSalesLineService productSalesLineService; + @Resource + @Lazy + private MesWmProductSalesService productSalesService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createOqc(MesQcOqcSaveReqVO createReqVO) { + // 1.1 校验数据 + validateOqcSaveData(createReqVO); + // 1.2 校验来源单据参数,并验证数据存在 + String sourceDocCode = validateAndGetSourceDocCode( + createReqVO.getSourceDocType(), createReqVO.getSourceLineId()); + // 1.3 根据产品 + 检验类型自动匹配模板 + MesQcTemplateItemDO templateItem = templateItemService.getRequiredTemplateByItemIdAndType( + createReqVO.getItemId(), MesQcTypeEnum.OQC.getType()); + Long templateId = templateItem.getTemplateId(); + + // 2. 插入主表 + MesQcOqcDO oqc = BeanUtils.toBean(createReqVO, MesQcOqcDO.class) + .setTemplateId(templateId) + .setSourceDocCode(sourceDocCode) + .setStatus(MesQcStatusEnum.DRAFT.getStatus()); + oqcMapper.insert(oqc); + + // 3. 从模板指标自动生成检验行 + oqcLineService.createLinesFromTemplate(oqc.getId(), templateId); + return oqc.getId(); + } + + @Override + public void updateOqc(MesQcOqcSaveReqVO updateReqVO) { + // 1.1 校验存在 + 草稿状态 + validateOqcStatusPrepare(updateReqVO.getId()); + // 1.2 校验数据 + validateOqcSaveData(updateReqVO); + + // 2. 更新 + MesQcOqcDO updateObj = BeanUtils.toBean(updateReqVO, MesQcOqcDO.class); + updateObj.setSourceDocType(null).setSourceDocId(null).setSourceLineId(null); // 不允许修改来源单据 + updateObj.setTemplateId(null); // 不允许修改模板 + updateObj.setItemId(null); // 不允许修改物料 + oqcMapper.updateById(updateObj); + } + + private void validateOqcSaveData(MesQcOqcSaveReqVO reqVO) { + // 校验编号唯一 + validateOqcCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验客户、物料、检测人员存在 + clientService.validateClientExists(reqVO.getClientId()); + itemService.validateItemExists(reqVO.getItemId()); + adminUserApi.validateUser(reqVO.getInspectorUserId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishOqc(Long id) { + // 1.1 校验存在 + 草稿状态 + MesQcOqcDO oqc = validateOqcStatusPrepare(id); + // 1.2 校验检测结论必填 + if (oqc.getCheckResult() == null) { + throw exception(QC_OQC_CHECK_RESULT_EMPTY); + } + + // 2. 更新状态为已完成 + MesQcOqcDO updateObj = new MesQcOqcDO() + .setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()); + oqcMapper.updateById(updateObj); + + // 3. 回写来源单据 + writeBackSourceDoc(oqc); + } + + /** + * 回写来源单据(OQC 完成后) + * + *

当来源为销售出库单时,调用 + * {@link MesWmProductSalesLineService#updateProductSalesLineWhenOqcFinish} + * 回写行的 oqcId、qualityStatus,并由该方法内部联动检查出库单整体状态 + * + * @param oqc 出货检验单 + */ + private void writeBackSourceDoc(MesQcOqcDO oqc) { + if (oqc.getSourceDocType() == null) { + return; + } + if (oqc.getSourceLineId() == null) { + throw new IllegalArgumentException( + "OQC 单[" + oqc.getId() + "] sourceDocType 非空但 sourceLineId 为空"); + } + + if (Objects.equals(oqc.getSourceDocType(), MesBizTypeConstants.WM_PRODUCT_SALES)) { + productSalesLineService.updateProductSalesLineWhenOqcFinish( + oqc.getSourceLineId(), oqc.getId(), oqc.getCheckResult()); + } else { + throw new IllegalArgumentException( + "OQC 单[" + oqc.getId() + "] sourceDocType=" + oqc.getSourceDocType() + " 无法识别,无法回写来源单据"); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteOqc(Long id) { + // 1. 校验存在 + 草稿状态 + validateOqcStatusPrepare(id); + + // 2.1 删除主表 + oqcMapper.deleteById(id); + // 2.2 级联删除行 + oqcLineService.deleteByOqcId(id); + // 2.3 级联删除缺陷记录 + defectRecordService.deleteListByQcTypeAndQcId(MesQcTypeEnum.OQC.getType(), id); + } + + @Override + public MesQcOqcDO validateOqcExists(Long id) { + MesQcOqcDO oqc = oqcMapper.selectById(id); + if (oqc == null) { + throw exception(QC_OQC_NOT_EXISTS); + } + return oqc; + } + + /** + * 校验出货检验单存在且为草稿状态 + */ + private MesQcOqcDO validateOqcStatusPrepare(Long id) { + MesQcOqcDO oqc = validateOqcExists(id); + if (ObjUtil.notEqual(oqc.getStatus(), MesQcStatusEnum.DRAFT.getStatus())) { + throw exception(QC_OQC_NOT_PREPARE); + } + return oqc; + } + + private void validateOqcCodeUnique(Long id, String code) { + MesQcOqcDO oqc = oqcMapper.selectByCode(code); + if (oqc == null) { + return; + } + if (ObjUtil.notEqual(oqc.getId(), id)) { + throw exception(QC_OQC_CODE_DUPLICATE); + } + } + + /** + * 校验来源单据参数,并验证数据存在 + * + * @param sourceDocType 来源单据类型 + * @param sourceLineId 来源单据行 ID + * @return 来源单据编号 + */ + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceLineId) { + if (sourceDocType == null || sourceLineId == null) { + return null; + } + if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_PRODUCT_SALES)) { + MesWmProductSalesLineDO salesLine = productSalesLineService.getProductSalesLine(sourceLineId); + if (salesLine != null && salesLine.getSalesId() != null) { + MesWmProductSalesDO sales = productSalesService.getProductSales(salesLine.getSalesId()); + return sales != null ? sales.getCode() : null; + } + } + return null; + } + + @Override + public MesQcOqcDO getOqc(Long id) { + return oqcMapper.selectById(id); + } + + @Override + public PageResult getOqcPage(MesQcOqcPageReqVO pageReqVO) { + return oqcMapper.selectPage(pageReqVO); + } + + @Override + public void recalculateDefectStats(Long oqcId, List records) { + // 1. 行级缺陷统计 + oqcLineService.recalculateLineDefectStats(oqcId, records); + + // 2.1 汇总主表的缺陷数量 + int totalCritical = 0, totalMajor = 0, totalMinor = 0; + for (MesQcDefectRecordDO record : records) { + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + totalCritical += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + totalMajor += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + totalMinor += quantity; + } else { + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); + } + } + // 2.2 计算缺陷率 + MesQcOqcDO oqc = validateOqcExists(oqcId); + BigDecimal criticalRate = BigDecimal.ZERO; + BigDecimal majorRate = BigDecimal.ZERO; + BigDecimal minorRate = BigDecimal.ZERO; + if (oqc.getCheckQuantity() != null && oqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + BigDecimal checkQty = oqc.getCheckQuantity(); + criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + } + // 2.3 更新主表 + MesQcOqcDO updateOqc = new MesQcOqcDO().setId(oqcId) + .setCriticalQuantity(totalCritical).setMajorQuantity(totalMajor).setMinorQuantity(totalMinor) + .setCriticalRate(criticalRate).setMajorRate(majorRate).setMinorRate(minorRate); + oqcMapper.updateById(updateOqc); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/pendinginspect/MesQcPendingInspectService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/pendinginspect/MesQcPendingInspectService.java new file mode 100644 index 000000000..dda258653 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/pendinginspect/MesQcPendingInspectService.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.mes.service.qc.pendinginspect; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectRespVO; + +/** + * MES 待检任务 Service 接口 + */ +public interface MesQcPendingInspectService { + + /** + * 获得待检任务分页 + * + * @param pageReqVO 分页查询 + * @return 待检任务分页 + */ + PageResult getPendingInspectPage(MesQcPendingInspectPageReqVO pageReqVO); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/pendinginspect/MesQcPendingInspectServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/pendinginspect/MesQcPendingInspectServiceImpl.java new file mode 100644 index 000000000..091e5194c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/pendinginspect/MesQcPendingInspectServiceImpl.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.service.qc.pendinginspect; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectRespVO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.pendinginspect.MesQcPendingInspectMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +/** + * MES 待检任务 Service 实现类 + */ +@Service +@Validated +public class MesQcPendingInspectServiceImpl implements MesQcPendingInspectService { + + @Resource + private MesQcPendingInspectMapper pendingInspectMapper; + + @Override + public PageResult getPendingInspectPage(MesQcPendingInspectPageReqVO pageReqVO) { + // 分页查询 + IPage page = MyBatisUtils.buildPage(pageReqVO); + pendingInspectMapper.selectQcPendingPage(page, + pageReqVO.getSourceDocCode(), pageReqVO.getQcType(), pageReqVO.getItemId()); + // 返回结果 + return new PageResult<>(page.getRecords(), page.getTotal()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineService.java new file mode 100644 index 000000000..299233580 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineService.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.mes.service.qc.rqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.line.MesQcRqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcLineDO; + +import java.util.List; + +/** + * MES 退货检验行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcRqcLineService { + + /** + * 校验退货检验行存在 + * + * @param id 编号 + * @return 退货检验行 + */ + MesQcRqcLineDO validateRqcLineExists(Long id); + + /** + * 获得退货检验行 + * + * @param id 编号 + * @return 退货检验行 + */ + MesQcRqcLineDO getRqcLine(Long id); + + /** + * 获得退货检验行分页 + * + * @param pageReqVO 分页查询 + * @return 退货检验行分页 + */ + PageResult getRqcLinePage(MesQcRqcLinePageReqVO pageReqVO); + + /** + * 从模板指标自动生成检验行 + * + * @param rqcId 退货检验单 ID + * @param templateId 模板 ID + */ + void createLinesFromTemplate(Long rqcId, Long templateId); + + /** + * 根据缺陷记录重新计算各行的缺陷统计数量 + * + * @param rqcId 退货检验单 ID + * @param records 缺陷记录列表 + */ + void recalculateLineDefectStats(Long rqcId, List records); + + /** + * 根据退货检验单 ID 获取所有行 + * + * @param rqcId 退货检验单 ID + * @return 行列表 + */ + List getRqcLineListByRqcId(Long rqcId); + + /** + * 根据退货检验单 ID 级联删除所有行 + * + * @param rqcId 退货检验单 ID + */ + void deleteByRqcId(Long rqcId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineServiceImpl.java new file mode 100644 index 000000000..f4351f228 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineServiceImpl.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.mes.service.qc.rqc; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.line.MesQcRqcLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc.MesQcRqcLineMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +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.*; + +/** + * MES 退货检验行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcRqcLineServiceImpl implements MesQcRqcLineService { + + @Resource + private MesQcRqcLineMapper rqcLineMapper; + @Resource + private MesQcTemplateIndicatorMapper templateIndicatorMapper; + + @Resource + private MesQcIndicatorService indicatorService; + + @Override + public MesQcRqcLineDO validateRqcLineExists(Long id) { + MesQcRqcLineDO line = rqcLineMapper.selectById(id); + if (line == null) { + throw exception(QC_RQC_LINE_NOT_EXISTS); + } + return line; + } + + @Override + public MesQcRqcLineDO getRqcLine(Long id) { + return rqcLineMapper.selectById(id); + } + + @Override + public PageResult getRqcLinePage(MesQcRqcLinePageReqVO pageReqVO) { + return rqcLineMapper.selectPage(pageReqVO); + } + + @Override + public void createLinesFromTemplate(Long rqcId, Long templateId) { + List templateIndicators = templateIndicatorMapper.selectListByTemplateId(templateId); + if (CollUtil.isEmpty(templateIndicators)) { + return; + } + Map indicatorMap = indicatorService.getIndicatorMap( + convertSet(templateIndicators, MesQcTemplateIndicatorDO::getIndicatorId)); + List lines = convertList(templateIndicators, templateIndicator -> { + MesQcIndicatorDO indicator = indicatorMap.get(templateIndicator.getIndicatorId()); + return new MesQcRqcLineDO() + .setRqcId(rqcId).setIndicatorId(templateIndicator.getIndicatorId()) + .setTool(indicator != null ? indicator.getTool() : null) + .setCheckMethod(templateIndicator.getCheckMethod()) + .setStandardValue(templateIndicator.getStandardValue()).setUnitMeasureId(templateIndicator.getUnitMeasureId()) + .setMaxThreshold(templateIndicator.getThresholdMax()).setMinThreshold(templateIndicator.getThresholdMin()) + .setCriticalQuantity(0).setMajorQuantity(0).setMinorQuantity(0); + }); + rqcLineMapper.insertBatch(lines); + } + + @Override + public void recalculateLineDefectStats(Long rqcId, List records) { + List lines = rqcLineMapper.selectListByRqcId(rqcId); + if (CollUtil.isEmpty(lines)) { + return; + } + List updateLines = new ArrayList<>(lines.size()); + for (MesQcRqcLineDO line : lines) { + int critical = 0, major = 0, minor = 0; + for (MesQcDefectRecordDO record : records) { + if (ObjUtil.notEqual(record.getLineId(), line.getId())) { + continue; + } + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + critical += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + major += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + minor += quantity; + } else { + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); + } + } + updateLines.add(new MesQcRqcLineDO().setId(line.getId()) + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor)); + } + for (MesQcRqcLineDO updateLine : updateLines) { + rqcLineMapper.updateById(updateLine); + } + } + + @Override + public List getRqcLineListByRqcId(Long rqcId) { + return rqcLineMapper.selectListByRqcId(rqcId); + } + + @Override + public void deleteByRqcId(Long rqcId) { + rqcLineMapper.deleteByRqcId(rqcId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcService.java new file mode 100644 index 000000000..efc0c8160 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcService.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.mes.service.qc.rqc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.MesQcRqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.MesQcRqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 退货检验单(RQC) Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcRqcService { + + /** + * 创建退货检验单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createRqc(@Valid MesQcRqcSaveReqVO createReqVO); + + /** + * 更新退货检验单 + * + * @param updateReqVO 更新信息 + */ + void updateRqc(@Valid MesQcRqcSaveReqVO updateReqVO); + + /** + * 完成退货检验单 + * + * @param id 编号 + */ + void finishRqc(Long id); + + /** + * 删除退货检验单 + * + * @param id 编号 + */ + void deleteRqc(Long id); + + /** + * 校验退货检验单存在 + * + * @param id 编号 + * @return 退货检验单 + */ + MesQcRqcDO validateRqcExists(Long id); + + /** + * 获得退货检验单 + * + * @param id 编号 + * @return 退货检验单 + */ + MesQcRqcDO getRqc(Long id); + + /** + * 获得退货检验单分页 + * + * @param pageReqVO 分页查询 + * @return 退货检验单分页 + */ + PageResult getRqcPage(MesQcRqcPageReqVO pageReqVO); + + /** + * 根据缺陷记录重新计算行级缺陷统计 + * + * @param rqcId 退货检验单 ID + * @param records 缺陷记录列表 + */ + void recalculateDefectStats(Long rqcId, List records); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java new file mode 100644 index 000000000..0d1d0bfac --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java @@ -0,0 +1,299 @@ +package cn.iocoder.yudao.module.mes.service.qc.rqc; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.MesQcRqcPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo.MesQcRqcSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc.MesQcRqcMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueService; +import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueLineService; +import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesLineService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 退货检验单(RQC) Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcRqcServiceImpl implements MesQcRqcService { + + @Resource + private MesQcRqcMapper rqcMapper; + @Resource + private MesQcTemplateItemService templateItemService; + @Resource + private MesQcRqcLineService rqcLineService; + @Resource + @Lazy + private MesMdItemService itemService; + @Resource + @Lazy + private MesQcDefectRecordService defectRecordService; + @Resource + @Lazy + private MesWmReturnIssueLineService returnIssueLineService; + @Resource + @Lazy + private MesWmReturnSalesLineService returnSalesLineService; + @Resource + @Lazy + private MesWmReturnIssueService returnIssueService; + @Resource + @Lazy + private MesWmReturnSalesService returnSalesService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createRqc(MesQcRqcSaveReqVO createReqVO) { + // 1.1 校验数据 + validateRqcSaveData(createReqVO); + // 1.2 根据物料 + 检验类型自动匹配模板 + MesQcTemplateItemDO templateItem = templateItemService.getRequiredTemplateByItemIdAndType( + createReqVO.getItemId(), createReqVO.getType()); + Long templateId = templateItem.getTemplateId(); + // 1.3 获取来源单据编号 + String sourceDocCode = validateAndGetSourceDocCode( + createReqVO.getSourceDocType(), createReqVO.getSourceDocId()); + + // 2. 插入主表 + MesQcRqcDO rqc = BeanUtils.toBean(createReqVO, MesQcRqcDO.class) + .setTemplateId(templateId) + .setSourceDocCode(sourceDocCode) + .setStatus(MesQcStatusEnum.DRAFT.getStatus()); + rqcMapper.insert(rqc); + + // 3. 从模板指标自动生成检验行 + rqcLineService.createLinesFromTemplate(rqc.getId(), templateId); + return rqc.getId(); + } + + @Override + public void updateRqc(MesQcRqcSaveReqVO updateReqVO) { + // 1.1 校验存在 + 草稿状态 + validateRqcStatusPrepare(updateReqVO.getId()); + // 1.2 校验数据 + validateRqcSaveData(updateReqVO); + + // 2. 更新 + MesQcRqcDO updateObj = BeanUtils.toBean(updateReqVO, MesQcRqcDO.class); + updateObj.setSourceDocType(null).setSourceDocId(null).setSourceLineId(null); // 不允许修改来源单据 + updateObj.setTemplateId(null); // 不允许修改模板 + updateObj.setItemId(null); // 不允许修改物料 + rqcMapper.updateById(updateObj); + } + + private void validateRqcSaveData(MesQcRqcSaveReqVO reqVO) { + // 校验编号唯一 + validateRqcCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验物料、检测人员存在 + itemService.validateItemExists(reqVO.getItemId()); + adminUserApi.validateUser(reqVO.getInspectorUserId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishRqc(Long id) { + // 1.1 校验存在 + 草稿状态 + MesQcRqcDO rqc = validateRqcStatusPrepare(id); + // 1.2 校验检测结论必填 + if (rqc.getCheckResult() == null) { + throw exception(QC_RQC_CHECK_RESULT_EMPTY); + } + // 1.3 校验合格品 + 不合格品 = 检测数量 + if (rqc.getCheckQuantity() != null && rqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + BigDecimal qualified = rqc.getQualifiedQuantity() != null ? rqc.getQualifiedQuantity() : BigDecimal.ZERO; + BigDecimal unqualified = rqc.getUnqualifiedQuantity() != null ? rqc.getUnqualifiedQuantity() : BigDecimal.ZERO; + if (qualified.add(unqualified).compareTo(rqc.getCheckQuantity()) != 0) { + throw exception(QC_RQC_QUANTITY_MISMATCH); + } + } + + // 2. 更新状态为已完成 + MesQcRqcDO updateObj = new MesQcRqcDO().setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()); + rqcMapper.updateById(updateObj); + + // 3. 回写来源单据 + writeBackSourceDoc(rqc); + } + + /** + * 回写来源单据(RQC 完成后) + * + *

根据 sourceDocType 分发: + *

    + *
  • WM_RETURN_ISSUE(生产退料单)→ 根据合格/不合格数量拆分行 + 更新 qualityStatus + 联动主单状态
  • + *
  • WM_RETURN_SALES(销售退货单)→ 同上
  • + *
+ * + * @param rqc 退货检验单 + */ + private void writeBackSourceDoc(MesQcRqcDO rqc) { + if (rqc.getSourceDocType() == null) { + return; + } + if (rqc.getSourceLineId() == null) { + throw new IllegalArgumentException( + "RQC 单[" + rqc.getId() + "] sourceDocType 非空但 sourceLineId 为空"); + } + + if (Objects.equals(rqc.getSourceDocType(), MesBizTypeConstants.WM_RETURN_ISSUE)) { + // 回写生产退料单行:拆分行 + 更新质量状态 + 联动主单状态 + returnIssueLineService.updateReturnIssueLineWhenRqcFinish( + rqc.getSourceLineId(), rqc.getSourceDocId(), rqc.getCheckResult(), + rqc.getQualifiedQuantity(), rqc.getUnqualifiedQuantity()); + } else if (Objects.equals(rqc.getSourceDocType(), MesBizTypeConstants.WM_RETURN_SALES)) { + // 回写销售退货单行:拆分行 + 更新质量状态 + 联动主单状态 + returnSalesLineService.updateReturnSalesLineWhenRqcFinish( + rqc.getSourceLineId(), rqc.getSourceDocId(), rqc.getCheckResult(), + rqc.getQualifiedQuantity(), rqc.getUnqualifiedQuantity()); + } else { + throw new IllegalArgumentException( + "RQC 单[" + rqc.getId() + "] sourceDocType=" + rqc.getSourceDocType() + " 无法识别,无法回写来源单据"); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteRqc(Long id) { + // 1. 校验存在 + 草稿状态 + validateRqcStatusPrepare(id); + + // 2.1 删除主表 + rqcMapper.deleteById(id); + // 2.2 级联删除行 + rqcLineService.deleteByRqcId(id); + // 2.3 级联删除缺陷记录 + defectRecordService.deleteListByQcTypeAndQcId(MesQcTypeEnum.RQC.getType(), id); + } + + @Override + public MesQcRqcDO validateRqcExists(Long id) { + MesQcRqcDO rqc = rqcMapper.selectById(id); + if (rqc == null) { + throw exception(QC_RQC_NOT_EXISTS); + } + return rqc; + } + + /** + * 校验退货检验单存在且为草稿状态 + * + * @param id 退货检验单 ID + * @return 退货检验单 + */ + private MesQcRqcDO validateRqcStatusPrepare(Long id) { + MesQcRqcDO rqc = validateRqcExists(id); + if (ObjUtil.notEqual(rqc.getStatus(), MesQcStatusEnum.DRAFT.getStatus())) { + throw exception(QC_RQC_NOT_PREPARE); + } + return rqc; + } + + private void validateRqcCodeUnique(Long id, String code) { + MesQcRqcDO rqc = rqcMapper.selectByCode(code); + if (rqc == null) { + return; + } + if (ObjUtil.notEqual(rqc.getId(), id)) { + throw exception(QC_RQC_CODE_DUPLICATE); + } + } + + @Override + public MesQcRqcDO getRqc(Long id) { + return rqcMapper.selectById(id); + } + + /** + * 根据来源单据类型 + 来源单据 ID,推导来源单据编码 + */ + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId) { + if (sourceDocType == null || sourceDocId == null) { + return null; + } + if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_RETURN_ISSUE)) { + return returnIssueService.getReturnIssue(sourceDocId).getCode(); + } else if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_RETURN_SALES)) { + return returnSalesService.getReturnSales(sourceDocId).getCode(); + } + return null; + } + + @Override + public PageResult getRqcPage(MesQcRqcPageReqVO pageReqVO) { + return rqcMapper.selectPage(pageReqVO); + } + + @Override + public void recalculateDefectStats(Long rqcId, List records) { + MesQcRqcDO rqc = validateRqcExists(rqcId); + // 1. 行级缺陷统计 + rqcLineService.recalculateLineDefectStats(rqcId, records); + + // 2.1 汇总主表的缺陷数量 + int totalCritical = 0; + int totalMajor = 0; + int totalMinor = 0; + for (MesQcDefectRecordDO record : records) { + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1); + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + totalCritical += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + totalMajor += quantity; + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + totalMinor += quantity; + } else { + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN); + } + } + // 2.2 计算缺陷率 + BigDecimal criticalRate = BigDecimal.ZERO; + BigDecimal majorRate = BigDecimal.ZERO; + BigDecimal minorRate = BigDecimal.ZERO; + if (rqc.getCheckQuantity() != null && rqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + BigDecimal checkQty = rqc.getCheckQuantity(); + criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100)) + .divide(checkQty, 2, RoundingMode.HALF_UP); + } + // 2.3 更新主表 + MesQcRqcDO updateRqc = new MesQcRqcDO().setId(rqcId) + .setCriticalQuantity(totalCritical).setMajorQuantity(totalMajor).setMinorQuantity(totalMinor) + .setCriticalRate(criticalRate).setMajorRate(majorRate).setMinorRate(minorRate); + rqcMapper.updateById(updateRqc); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorService.java new file mode 100644 index 000000000..9e28f4113 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.service.qc.template; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.MesQcTemplateIndicatorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.MesQcTemplateIndicatorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; +import jakarta.validation.Valid; + +/** + * MES 质检方案-检测指标项 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcTemplateIndicatorService { + + /** + * 创建检测指标项 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTemplateIndicator(@Valid MesQcTemplateIndicatorSaveReqVO createReqVO); + + /** + * 更新检测指标项 + * + * @param updateReqVO 更新信息 + */ + void updateTemplateIndicator(@Valid MesQcTemplateIndicatorSaveReqVO updateReqVO); + + /** + * 删除检测指标项 + * + * @param id 编号 + */ + void deleteTemplateIndicator(Long id); + + /** + * 获得检测指标项 + * + * @param id 编号 + * @return 检测指标项 + */ + MesQcTemplateIndicatorDO getTemplateIndicator(Long id); + + /** + * 获得检测指标项分页 + * + * @param pageReqVO 分页查询 + * @return 检测指标项分页 + */ + PageResult getTemplateIndicatorPage(MesQcTemplateIndicatorPageReqVO pageReqVO); + + /** + * 根据方案编号删除所有检测指标项 + * + * @param templateId 质检方案编号 + */ + void deleteTemplateIndicatorByTemplateId(Long templateId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorServiceImpl.java new file mode 100644 index 000000000..afe355ee2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorServiceImpl.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.mes.service.qc.template; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.MesQcTemplateIndicatorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.MesQcTemplateIndicatorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.QC_TEMPLATE_INDICATOR_NOT_EXISTS; + +/** + * MES 质检方案-检测指标项 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcTemplateIndicatorServiceImpl implements MesQcTemplateIndicatorService { + + @Resource + private MesQcTemplateIndicatorMapper templateIndicatorMapper; + + @Resource + @Lazy + private MesQcTemplateService templateService; + + @Override + public Long createTemplateIndicator(MesQcTemplateIndicatorSaveReqVO createReqVO) { + // 校验方案存在 + templateService.validateTemplateExists(createReqVO.getTemplateId()); + + // 插入 + MesQcTemplateIndicatorDO indicator = BeanUtils.toBean(createReqVO, MesQcTemplateIndicatorDO.class); + templateIndicatorMapper.insert(indicator); + return indicator.getId(); + } + + @Override + public void updateTemplateIndicator(MesQcTemplateIndicatorSaveReqVO updateReqVO) { + // 校验存在 + validateTemplateIndicatorExists(updateReqVO.getId()); + + // 更新 + MesQcTemplateIndicatorDO updateObj = BeanUtils.toBean(updateReqVO, MesQcTemplateIndicatorDO.class); + templateIndicatorMapper.updateById(updateObj); + } + + @Override + public void deleteTemplateIndicator(Long id) { + // 校验存在 + validateTemplateIndicatorExists(id); + // 删除 + templateIndicatorMapper.deleteById(id); + } + + private void validateTemplateIndicatorExists(Long id) { + if (templateIndicatorMapper.selectById(id) == null) { + throw exception(QC_TEMPLATE_INDICATOR_NOT_EXISTS); + } + } + + @Override + public MesQcTemplateIndicatorDO getTemplateIndicator(Long id) { + return templateIndicatorMapper.selectById(id); + } + + @Override + public PageResult getTemplateIndicatorPage(MesQcTemplateIndicatorPageReqVO pageReqVO) { + return templateIndicatorMapper.selectPage(pageReqVO); + } + + @Override + public void deleteTemplateIndicatorByTemplateId(Long templateId) { + templateIndicatorMapper.deleteByTemplateId(templateId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemService.java new file mode 100644 index 000000000..0fd23fcc0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemService.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.service.qc.template; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item.MesQcTemplateItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item.MesQcTemplateItemSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import jakarta.validation.Valid; + +/** + * MES 质检方案-产品关联 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcTemplateItemService { + + /** + * 创建产品关联 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTemplateItem(@Valid MesQcTemplateItemSaveReqVO createReqVO); + + /** + * 更新产品关联 + * + * @param updateReqVO 更新信息 + */ + void updateTemplateItem(@Valid MesQcTemplateItemSaveReqVO updateReqVO); + + /** + * 删除产品关联 + * + * @param id 编号 + */ + void deleteTemplateItem(Long id); + + /** + * 获得产品关联 + * + * @param id 编号 + * @return 产品关联 + */ + MesQcTemplateItemDO getTemplateItem(Long id); + + /** + * 获得产品关联分页 + * + * @param pageReqVO 分页查询 + * @return 产品关联分页 + */ + PageResult getTemplateItemPage(MesQcTemplateItemPageReqVO pageReqVO); + + /** + * 根据方案编号删除所有产品关联 + * + * @param templateId 质检方案编号 + */ + void deleteTemplateItemByTemplateId(Long templateId); + + /** + * 根据产品物料 ID 和 QC 类型查找检验模板的产品关联(必须存在,否则抛异常) + * + * @param itemId 产品物料 ID + * @param qcType 检测种类(枚举 {@link MesQcTypeEnum}) + * @return 匹配的产品关联 + */ + MesQcTemplateItemDO getRequiredTemplateByItemIdAndType(Long itemId, Integer qcType); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemServiceImpl.java new file mode 100644 index 000000000..2b49345f8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateItemServiceImpl.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.mes.service.qc.template; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item.MesQcTemplateItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item.MesQcTemplateItemSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateItemMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 质检方案-产品关联 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcTemplateItemServiceImpl implements MesQcTemplateItemService { + + @Resource + private MesQcTemplateItemMapper templateItemMapper; + + @Resource + @Lazy + private MesQcTemplateService templateService; + + @Override + public Long createTemplateItem(MesQcTemplateItemSaveReqVO createReqVO) { + // 校验保存参数 + validateTemplateItemSaveData(createReqVO); + + // 插入 + MesQcTemplateItemDO item = BeanUtils.toBean(createReqVO, MesQcTemplateItemDO.class); + templateItemMapper.insert(item); + return item.getId(); + } + + @Override + public void updateTemplateItem(MesQcTemplateItemSaveReqVO updateReqVO) { + // 校验保存参数 + validateTemplateItemSaveData(updateReqVO); + + // 更新 + MesQcTemplateItemDO updateObj = BeanUtils.toBean(updateReqVO, MesQcTemplateItemDO.class); + templateItemMapper.updateById(updateObj); + } + + private void validateTemplateItemSaveData(MesQcTemplateItemSaveReqVO saveReqVO) { + if (saveReqVO.getId() != null) { + // 校验存在 + validateTemplateItemExists(saveReqVO.getId()); + } + // 校验方案存在 + templateService.validateTemplateExists(saveReqVO.getTemplateId()); + // 校验产品在此方案中唯一 + validateTemplateItemNotDuplicate(saveReqVO.getId(), saveReqVO.getTemplateId(), saveReqVO.getItemId()); + } + + @Override + public void deleteTemplateItem(Long id) { + // 校验存在 + validateTemplateItemExists(id); + // 删除 + templateItemMapper.deleteById(id); + } + + private void validateTemplateItemExists(Long id) { + if (templateItemMapper.selectById(id) == null) { + throw exception(QC_TEMPLATE_ITEM_NOT_EXISTS); + } + } + + private void validateTemplateItemNotDuplicate(Long id, Long templateId, Long itemId) { + MesQcTemplateItemDO existing = templateItemMapper.selectByTemplateIdAndItemId(templateId, itemId); + if (existing == null) { + return; + } + if (ObjUtil.notEqual(existing.getId(), id)) { + throw exception(QC_TEMPLATE_ITEM_DUPLICATE); + } + } + + @Override + public MesQcTemplateItemDO getTemplateItem(Long id) { + return templateItemMapper.selectById(id); + } + + @Override + public PageResult getTemplateItemPage(MesQcTemplateItemPageReqVO pageReqVO) { + return templateItemMapper.selectPage(pageReqVO); + } + + @Override + public void deleteTemplateItemByTemplateId(Long templateId) { + templateItemMapper.deleteByTemplateId(templateId); + } + + @Override + public MesQcTemplateItemDO getRequiredTemplateByItemIdAndType(Long itemId, Integer qcType) { + // 1. 查出 itemId 关联的所有 templateItem + List templateItems = templateItemMapper.selectListByItemId(itemId); + if (CollUtil.isEmpty(templateItems)) { + throw exception(QC_NO_TEMPLATE); + } + // 2. 筛选 types 包含 qcType 且状态为开启的模板 + List templates = templateService.getTemplateList( + convertSet(templateItems, MesQcTemplateItemDO::getTemplateId)); + MesQcTemplateDO matchedTemplate = findFirst(templates, + t -> CommonStatusEnum.isEnable(t.getStatus()) && CollUtil.contains(t.getTypes(), qcType)); + if (matchedTemplate == null) { + throw exception(QC_NO_TEMPLATE); + } + // 3. 返回对应的 templateItem + return findFirst(templateItems, + item -> Objects.equals(item.getTemplateId(), matchedTemplate.getId())); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java new file mode 100644 index 000000000..7cd713c2a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.service.qc.template; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplatePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplateSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 质检方案 Service 接口 + * + * @author 芋道源码 + */ +public interface MesQcTemplateService { + + /** + * 创建质检方案 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTemplate(@Valid MesQcTemplateSaveReqVO createReqVO); + + /** + * 更新质检方案 + * + * @param updateReqVO 更新信息 + */ + void updateTemplate(@Valid MesQcTemplateSaveReqVO updateReqVO); + + /** + * 删除质检方案(级联删除检测指标项和产品关联) + * + * @param id 编号 + */ + void deleteTemplate(Long id); + + /** + * 获得质检方案 + * + * @param id 编号 + * @return 质检方案 + */ + MesQcTemplateDO getTemplate(Long id); + + /** + * 获得质检方案分页 + * + * @param pageReqVO 分页查询 + * @return 质检方案分页 + */ + PageResult getTemplatePage(MesQcTemplatePageReqVO pageReqVO); + + /** + * 获得质检方案列表(用于下拉选择) + * + * @return 质检方案列表 + */ + List getTemplateList(); + + /** + * 获得质检方案列表 + * + * @param ids 编号数组 + * @return 质检方案列表 + */ + List getTemplateList(Collection ids); + + /** + * 获得质检方案 Map + * + * @param ids 编号数组 + * @return 质检方案 Map + */ + default Map getTemplateMap(Collection ids) { + return convertMap(getTemplateList(ids), MesQcTemplateDO::getId); + } + + /** + * 校验质检方案存在 + * + * @param id 编号 + * @return 质检方案 + */ + MesQcTemplateDO validateTemplateExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java new file mode 100644 index 000000000..0908f7f69 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.mes.service.qc.template; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplatePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.MesQcTemplateSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 质检方案 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesQcTemplateServiceImpl implements MesQcTemplateService { + + @Resource + private MesQcTemplateMapper templateMapper; + @Resource + @Lazy + private MesQcTemplateIndicatorService templateIndicatorService; + @Resource + @Lazy + private MesQcTemplateItemService templateItemService; + + @Override + public Long createTemplate(MesQcTemplateSaveReqVO createReqVO) { + // 校验编码唯一 + validateTemplateCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesQcTemplateDO template = BeanUtils.toBean(createReqVO, MesQcTemplateDO.class); + templateMapper.insert(template); + return template.getId(); + } + + @Override + public void updateTemplate(MesQcTemplateSaveReqVO updateReqVO) { + // 校验存在 + validateTemplateExists(updateReqVO.getId()); + // 校验编码唯一 + validateTemplateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesQcTemplateDO updateObj = BeanUtils.toBean(updateReqVO, MesQcTemplateDO.class); + templateMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteTemplate(Long id) { + // 校验存在 + validateTemplateExists(id); + + // 删除主表 + templateMapper.deleteById(id); + // 级联删除检测指标项 + templateIndicatorService.deleteTemplateIndicatorByTemplateId(id); + // 级联删除产品关联 + templateItemService.deleteTemplateItemByTemplateId(id); + } + + @Override + public MesQcTemplateDO validateTemplateExists(Long id) { + MesQcTemplateDO template = templateMapper.selectById(id); + if (template == null) { + throw exception(QC_TEMPLATE_NOT_EXISTS); + } + return template; + } + + private void validateTemplateCodeUnique(Long id, String code) { + MesQcTemplateDO template = templateMapper.selectByCode(code); + if (template == null) { + return; + } + if (ObjUtil.notEqual(template.getId(), id)) { + throw exception(QC_TEMPLATE_CODE_DUPLICATE); + } + } + + @Override + public MesQcTemplateDO getTemplate(Long id) { + return templateMapper.selectById(id); + } + + @Override + public PageResult getTemplatePage(MesQcTemplatePageReqVO pageReqVO) { + return templateMapper.selectPage(pageReqVO); + } + + @Override + public List getTemplateList() { + return templateMapper.selectList(); + } + + @Override + public List getTemplateList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return templateMapper.selectByIds(ids); + } + +} + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolService.java new file mode 100644 index 000000000..243faf276 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.mes.service.tm.tool; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.MesTmToolPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.MesTmToolSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 工具台账 Service 接口 + * + * @author 芋道源码 + */ +public interface MesTmToolService { + + /** + * 创建工具 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTool(@Valid MesTmToolSaveReqVO createReqVO); + + /** + * 更新工具 + * + * @param updateReqVO 更新信息 + */ + void updateTool(@Valid MesTmToolSaveReqVO updateReqVO); + + /** + * 删除工具 + * + * @param id 编号 + */ + void deleteTool(Long id); + + /** + * 获得工具 + * + * @param id 编号 + * @return 工具 + */ + MesTmToolDO getTool(Long id); + + /** + * 获得工具分页 + * + * @param pageReqVO 分页查询 + * @return 工具分页 + */ + PageResult getToolPage(MesTmToolPageReqVO pageReqVO); + + /** + * 获得工具列表 + * + * @return 工具列表 + */ + List getToolList(); + + /** + * 获得工具列表 + * + * @param ids 编号列表 + * @return 工具列表 + */ + List getToolList(Collection ids); + + /** + * 获得工具 Map + * + * @param ids 编号列表 + * @return 工具 Map + */ + default Map getToolMap(Collection ids) { + return convertMap(getToolList(ids), MesTmToolDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolServiceImpl.java new file mode 100644 index 000000000..fe707fdf1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolServiceImpl.java @@ -0,0 +1,135 @@ +package cn.iocoder.yudao.module.mes.service.tm.tool; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.MesTmToolPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.MesTmToolSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO; +import cn.iocoder.yudao.module.mes.dal.mysql.tm.tool.MesTmToolMapper; +import cn.iocoder.yudao.module.mes.enums.tm.MesTmMaintenTypeEnum; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.TM_TOOL_CODE_DUPLICATE; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.TM_TOOL_NOT_EXISTS; + +/** + * MES 工具台账 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesTmToolServiceImpl implements MesTmToolService { + + @Resource + private MesTmToolMapper toolMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private MesTmToolTypeService toolTypeService; + + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createTool(MesTmToolSaveReqVO createReqVO) { + // 校验数据 + validateToolSaveData(null, createReqVO); + + // 插入 + MesTmToolDO tool = BeanUtils.toBean(createReqVO, MesTmToolDO.class); + toolMapper.insert(tool); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.TOOL.getValue(), + tool.getId(), tool.getCode(), tool.getName()); + return tool.getId(); + } + + @Override + public void updateTool(MesTmToolSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateToolExists(updateReqVO.getId()); + // 1.2 校验数据 + validateToolSaveData(updateReqVO.getId(), updateReqVO); + + // 2.1 保养类型互斥清理 + if (Objects.equals(updateReqVO.getMaintenType(), MesTmMaintenTypeEnum.REGULAR.getType())) { + updateReqVO.setNextMaintenPeriod(null); + } else if (Objects.equals(updateReqVO.getMaintenType(), MesTmMaintenTypeEnum.USAGE.getType())) { + updateReqVO.setNextMaintenDate(null); + } + // 2.2 更新 + MesTmToolDO updateObj = BeanUtils.toBean(updateReqVO, MesTmToolDO.class); + toolMapper.updateById(updateObj); + } + + private void validateToolSaveData(Long id, MesTmToolSaveReqVO reqVO) { + // 校验工具类型存在 + toolTypeService.validateToolTypeExists(reqVO.getToolTypeId()); + // 校验编码唯一 + validateToolCodeUnique(id, reqVO.getCode()); + } + + @Override + public void deleteTool(Long id) { + // 校验存在 + validateToolExists(id); + // 删除 + toolMapper.deleteById(id); + } + + private void validateToolExists(Long id) { + if (toolMapper.selectById(id) == null) { + throw exception(TM_TOOL_NOT_EXISTS); + } + } + + private void validateToolCodeUnique(Long id, String code) { + if (code == null) { + return; + } + MesTmToolDO tool = toolMapper.selectByCode(code); + if (tool == null) { + return; + } + if (ObjUtil.notEqual(tool.getId(), id)) { + throw exception(TM_TOOL_CODE_DUPLICATE); + } + } + + @Override + public MesTmToolDO getTool(Long id) { + return toolMapper.selectById(id); + } + + @Override + public PageResult getToolPage(MesTmToolPageReqVO pageReqVO) { + return toolMapper.selectPage(pageReqVO); + } + + @Override + public List getToolList() { + return toolMapper.selectList(); + } + + @Override + public List getToolList(Collection ids) { + if (ids == null || ids.isEmpty()) { + return List.of(); + } + return toolMapper.selectBatchIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeService.java new file mode 100644 index 000000000..c59975d61 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeService.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.mes.service.tm.tool; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolTypeDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 工具类型 Service 接口 + * + * @author 芋道源码 + */ +public interface MesTmToolTypeService { + + /** + * 创建工具类型 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createToolType(@Valid MesTmToolTypeSaveReqVO createReqVO); + + /** + * 更新工具类型 + * + * @param updateReqVO 更新信息 + */ + void updateToolType(@Valid MesTmToolTypeSaveReqVO updateReqVO); + + /** + * 删除工具类型 + * + * @param id 编号 + */ + void deleteToolType(Long id); + + /** + * 获得工具类型 + * + * @param id 编号 + * @return 工具类型 + */ + MesTmToolTypeDO getToolType(Long id); + + /** + * 获得工具类型分页 + * + * @param pageReqVO 分页查询 + * @return 工具类型分页 + */ + PageResult getToolTypePage(MesTmToolTypePageReqVO pageReqVO); + + /** + * 获得工具类型列表 + * + * @return 工具类型列表 + */ + List getToolTypeList(); + + /** + * 校验工具类型是否存在 + * + * @param id 编号 + */ + void validateToolTypeExists(Long id); + + /** + * 获得工具类型列表 + * + * @param ids 编号数组 + * @return 工具类型列表 + */ + List getToolTypeList(Collection ids); + + /** + * 获得工具类型 Map + * + * @param ids 编号数组 + * @return 工具类型 Map + */ + default Map getToolTypeMap(Collection ids) { + return convertMap(getToolTypeList(ids), MesTmToolTypeDO::getId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeServiceImpl.java new file mode 100644 index 000000000..6a5d1f610 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeServiceImpl.java @@ -0,0 +1,132 @@ +package cn.iocoder.yudao.module.mes.service.tm.tool; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolTypeDO; +import cn.iocoder.yudao.module.mes.dal.mysql.tm.tool.MesTmToolMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.tm.tool.MesTmToolTypeMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import cn.hutool.core.util.ObjUtil; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 工具类型 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesTmToolTypeServiceImpl implements MesTmToolTypeService { + + @Resource + private MesTmToolTypeMapper toolTypeMapper; + + @Resource + private MesTmToolMapper toolMapper; + + @Override + public Long createToolType(MesTmToolTypeSaveReqVO createReqVO) { + // 校验数据 + validateToolTypeSaveData(null, createReqVO); + + // 插入 + MesTmToolTypeDO toolType = BeanUtils.toBean(createReqVO, MesTmToolTypeDO.class); + toolTypeMapper.insert(toolType); + return toolType.getId(); + } + + @Override + public void updateToolType(MesTmToolTypeSaveReqVO updateReqVO) { + // 校验存在 + validateToolTypeExists(updateReqVO.getId()); + // 校验数据 + validateToolTypeSaveData(updateReqVO.getId(), updateReqVO); + + // 更新 + MesTmToolTypeDO updateObj = BeanUtils.toBean(updateReqVO, MesTmToolTypeDO.class); + toolTypeMapper.updateById(updateObj); + } + + private void validateToolTypeSaveData(Long id, MesTmToolTypeSaveReqVO saveReqVO) { + // 校验编码唯一 + validateToolTypeCodeUnique(id, saveReqVO.getCode()); + // 校验名称唯一 + validateToolTypeNameUnique(id, saveReqVO.getName()); + } + + @Override + public void deleteToolType(Long id) { + // 校验存在 + validateToolTypeExists(id); + // 校验是否被工具引用 + if (toolMapper.selectCountByToolTypeId(id) > 0) { + throw exception(TM_TOOL_TYPE_HAS_TOOL); + } + + // 删除 + toolTypeMapper.deleteById(id); + } + + @Override + public void validateToolTypeExists(Long id) { + if (toolTypeMapper.selectById(id) == null) { + throw exception(TM_TOOL_TYPE_NOT_EXISTS); + } + } + + private void validateToolTypeCodeUnique(Long id, String code) { + MesTmToolTypeDO toolType = toolTypeMapper.selectByCode(code); + if (toolType == null) { + return; + } + if (ObjUtil.notEqual(toolType.getId(), id)) { + throw exception(TM_TOOL_TYPE_CODE_DUPLICATE); + } + } + + private void validateToolTypeNameUnique(Long id, String name) { + MesTmToolTypeDO toolType = toolTypeMapper.selectByName(name); + if (toolType == null) { + return; + } + if (ObjUtil.notEqual(toolType.getId(), id)) { + throw exception(TM_TOOL_TYPE_NAME_DUPLICATE); + } + } + + @Override + public MesTmToolTypeDO getToolType(Long id) { + return toolTypeMapper.selectById(id); + } + + @Override + public PageResult getToolTypePage(MesTmToolTypePageReqVO pageReqVO) { + return toolTypeMapper.selectPage(pageReqVO); + } + + @Override + public List getToolTypeList() { + return toolTypeMapper.selectList(); + } + + @Override + public List getToolTypeList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return toolTypeMapper.selectByIds(ids); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java new file mode 100644 index 000000000..eecdc8d29 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.mes.service.wm.arrivalnotice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; +import java.util.List; + +/** + * MES 到货通知单行 Service 接口 + */ +public interface MesWmArrivalNoticeLineService { + + /** + * 创建到货通知单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createArrivalNoticeLine(@Valid MesWmArrivalNoticeLineSaveReqVO createReqVO); + + /** + * 修改到货通知单行 + * + * @param updateReqVO 修改信息 + */ + void updateArrivalNoticeLine(@Valid MesWmArrivalNoticeLineSaveReqVO updateReqVO); + + /** + * 删除到货通知单行 + * + * @param id 编号 + */ + void deleteArrivalNoticeLine(Long id); + + /** + * 获得到货通知单行 + * + * @param id 编号 + * @return 到货通知单行 + */ + MesWmArrivalNoticeLineDO getArrivalNoticeLine(Long id); + + /** + * 获得到货通知单行分页 + * + * @param pageReqVO 分页参数 + * @return 到货通知单行分页 + */ + PageResult getArrivalNoticeLinePage(MesWmArrivalNoticeLinePageReqVO pageReqVO); + + /** + * 按通知单编号获得行列表 + * + * @param noticeId 通知单编号 + * @return 行列表 + */ + List getArrivalNoticeLineListByNoticeId(Long noticeId); + + /** + * 按通知单编号批量删除行 + * + * @param noticeId 通知单编号 + */ + void deleteArrivalNoticeLineByNoticeId(Long noticeId); + + /** + * IQC 检验完成后回写行数据 + * + * @param lineId 行编号 + * @param iqcId IQC 检验单编号 + * @param qualifiedQuantity 合格数量 + */ + void updateArrivalNoticeLineWhenIqcFinish(Long lineId, Long iqcId, BigDecimal qualifiedQuantity); + + /** + * 校验到货通知单行存在 + * + * @param id 编号 + * @return 到货通知单行 + */ + MesWmArrivalNoticeLineDO validateArrivalNoticeLineExists(Long id); + + /** + * 校验到货通知单行存在且属于指定的到货通知单 + * + * @param lineId 行编号 + * @param noticeId 到货通知单编号 + * @return 到货通知单行 + */ + MesWmArrivalNoticeLineDO validateArrivalNoticeLineExists(Long lineId, Long noticeId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java new file mode 100644 index 000000000..b181cac04 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java @@ -0,0 +1,142 @@ +package cn.iocoder.yudao.module.mes.service.wm.arrivalnotice; + +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 到货通知单行 Service 实现类 + */ +@Service +@Validated +public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLineService { + + @Resource + private MesWmArrivalNoticeLineMapper arrivalNoticeLineMapper; + + @Resource + @Lazy + private MesWmArrivalNoticeService arrivalNoticeService; + @Resource + private MesMdItemService itemService; + + @Override + public Long createArrivalNoticeLine(MesWmArrivalNoticeLineSaveReqVO createReqVO) { + // 校验数据 + validateArrivalNoticeLineSaveData(createReqVO); + + // 插入 + MesWmArrivalNoticeLineDO line = BeanUtils.toBean(createReqVO, MesWmArrivalNoticeLineDO.class); + initQualifiedQuantityIfNoIqc(line); + arrivalNoticeLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateArrivalNoticeLine(MesWmArrivalNoticeLineSaveReqVO updateReqVO) { + // 校验存在 + MesWmArrivalNoticeLineDO line = validateArrivalNoticeLineExists(updateReqVO.getId()); + // 校验数据 + updateReqVO.setNoticeId(line.getNoticeId()); + validateArrivalNoticeLineSaveData(updateReqVO); + + // 更新 + MesWmArrivalNoticeLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmArrivalNoticeLineDO.class); + initQualifiedQuantityIfNoIqc(updateObj); + arrivalNoticeLineMapper.updateById(updateObj); + } + + private void validateArrivalNoticeLineSaveData(MesWmArrivalNoticeLineSaveReqVO reqVO) { + // 校验父单据存在且为草稿状态 + arrivalNoticeService.validateArrivalNoticeExistsAndDraft(reqVO.getNoticeId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + } + + /** + * 初始化合格品数量: + * 1. 如果不需要 IQC 检验,则合格品数量直接 = 接收数量; + * 2. 否则,合格品数量由对应的 IQC 检验单负责更新(见 {@link #updateArrivalNoticeLineWhenIqcFinish}) + */ + private void initQualifiedQuantityIfNoIqc(MesWmArrivalNoticeLineDO line) { + if (BooleanUtil.isFalse(line.getIqcCheckFlag())) { + line.setQualifiedQuantity(line.getArrivalQuantity()); + } + } + + @Override + public void deleteArrivalNoticeLine(Long id) { + // 校验存在 + MesWmArrivalNoticeLineDO line = validateArrivalNoticeLineExists(id); + // 校验父单据存在且为草稿状态 + arrivalNoticeService.validateArrivalNoticeExistsAndDraft(line.getNoticeId()); + + // 删除 + arrivalNoticeLineMapper.deleteById(id); + } + + @Override + public MesWmArrivalNoticeLineDO getArrivalNoticeLine(Long id) { + return arrivalNoticeLineMapper.selectById(id); + } + + @Override + public PageResult getArrivalNoticeLinePage(MesWmArrivalNoticeLinePageReqVO pageReqVO) { + return arrivalNoticeLineMapper.selectPage(pageReqVO); + } + + @Override + public List getArrivalNoticeLineListByNoticeId(Long noticeId) { + return arrivalNoticeLineMapper.selectListByNoticeId(noticeId); + } + + @Override + public void deleteArrivalNoticeLineByNoticeId(Long noticeId) { + arrivalNoticeLineMapper.deleteByNoticeId(noticeId); + } + + @Override + public void updateArrivalNoticeLineWhenIqcFinish(Long lineId, Long iqcId, BigDecimal qualifiedQuantity) { + // 校验行存在 + validateArrivalNoticeLineExists(lineId); + // 更新 + arrivalNoticeLineMapper.updateById(new MesWmArrivalNoticeLineDO() + .setId(lineId).setIqcId(iqcId).setQualifiedQuantity(qualifiedQuantity)); + } + + @Override + public MesWmArrivalNoticeLineDO validateArrivalNoticeLineExists(Long id) { + MesWmArrivalNoticeLineDO line = arrivalNoticeLineMapper.selectById(id); + if (line == null) { + throw exception(WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS); + } + return line; + } + + @Override + public MesWmArrivalNoticeLineDO validateArrivalNoticeLineExists(Long lineId, Long noticeId) { + MesWmArrivalNoticeLineDO line = validateArrivalNoticeLineExists(lineId); + // 进一步校验行的 noticeId 与传入的 noticeId 是否匹配 + if (noticeId != null && ObjUtil.notEqual(line.getNoticeId(), noticeId)) { + throw exception(WM_ARRIVAL_NOTICE_LINE_NOT_MATCH); + } + return line; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java new file mode 100644 index 000000000..04109ce61 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java @@ -0,0 +1,135 @@ +package cn.iocoder.yudao.module.mes.service.wm.arrivalnotice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 到货通知单 Service 接口 + */ +public interface MesWmArrivalNoticeService { + + /** + * 创建到货通知单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createArrivalNotice(@Valid MesWmArrivalNoticeSaveReqVO createReqVO); + + /** + * 修改到货通知单 + * + * @param updateReqVO 修改信息 + */ + void updateArrivalNotice(@Valid MesWmArrivalNoticeSaveReqVO updateReqVO); + + /** + * 删除到货通知单(级联删除行) + * + * @param id 编号 + */ + void deleteArrivalNotice(Long id); + + /** + * 获得到货通知单 + * + * @param id 编号 + * @return 到货通知单 + */ + MesWmArrivalNoticeDO getArrivalNotice(Long id); + + /** + * 获得到货通知单分页 + * + * @param pageReqVO 分页参数 + * @return 到货通知单分页 + */ + PageResult getArrivalNoticePage(MesWmArrivalNoticePageReqVO pageReqVO); + + /** + * 提交到货通知单(草稿 → 待质检/待入库) + * + * @param id 编号 + */ + void submitArrivalNotice(Long id); + + /** + * IQC 检验完成后回写到货通知单(更新行 + 尝试推进主表状态) + * + * @param id 到货通知单编号 + * @param lineId 到货通知单行编号 + * @param iqcId IQC 检验单编号 + * @param qualifiedQuantity 合格数量 + */ + void updateArrivalNoticeWhenIqcFinish(Long id, Long lineId, Long iqcId, BigDecimal qualifiedQuantity); + + /** + * 完成到货通知单(待入库 → 已完成),内部调用 + * + * @param id 编号 + */ + void finishArrivalNotice(Long id); + + /** + * 按编号集合获得到货通知单列表 + * + * @param ids 编号集合 + * @return 到货通知单列表 + */ + List getArrivalNoticeList(Collection ids); + + default Map getArrivalNoticeMap(Collection ids) { + return convertMap(getArrivalNoticeList(ids), MesWmArrivalNoticeDO::getId); + } + + /** + * 校验到货通知单存在 + * + * @param id 编号 + * @return 到货通知单 + */ + MesWmArrivalNoticeDO validateArrivalNoticeExists(Long id); + + /** + * 校验到货通知单存在且为草稿状态 + * + * @param id 编号 + * @return 到货通知单 + */ + MesWmArrivalNoticeDO validateArrivalNoticeExistsAndDraft(Long id); + + /** + * 校验到货通知单和行存在,且行属于该通知单 + * + * @param noticeId 到货通知单 ID + * @param lineId 到货通知单行 ID + */ + void validateArrivalNoticeAndLineExists(Long noticeId, Long lineId); + + /** + * 按状态获得到货通知单列表 + * + * @param status 状态 + * @return 到货通知单列表 + */ + List getArrivalNoticeListByStatus(Integer status); + + /** + * 查询指定供应商的到货通知单数量 + * + * @param vendorId 供应商编号 + * @return 数量 + */ + Long getArrivalNoticeCountByVendorId(Long vendorId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java new file mode 100644 index 000000000..0e41cea03 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java @@ -0,0 +1,220 @@ +package cn.iocoder.yudao.module.mes.service.wm.arrivalnotice; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 到货通知单 Service 实现类 + */ +@Service +@Validated +@Slf4j +public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService { + + @Resource + private MesWmArrivalNoticeMapper arrivalNoticeMapper; + + @Resource + private MesWmArrivalNoticeLineService arrivalNoticeLineService; + + @Override + public Long createArrivalNotice(MesWmArrivalNoticeSaveReqVO createReqVO) { + // 校验编码唯一 + validateCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesWmArrivalNoticeDO notice = BeanUtils.toBean(createReqVO, MesWmArrivalNoticeDO.class); + notice.setStatus(MesWmArrivalNoticeStatusEnum.PREPARE.getStatus()); + arrivalNoticeMapper.insert(notice); + return notice.getId(); + } + + @Override + public void updateArrivalNotice(MesWmArrivalNoticeSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateArrivalNoticeExistsAndDraft(updateReqVO.getId()); + // 校验编码唯一 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesWmArrivalNoticeDO updateObj = BeanUtils.toBean(updateReqVO, MesWmArrivalNoticeDO.class); + arrivalNoticeMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteArrivalNotice(Long id) { + // 校验存在 + 草稿状态 + validateArrivalNoticeExistsAndDraft(id); + + // 级联删除行 + arrivalNoticeLineService.deleteArrivalNoticeLineByNoticeId(id); + // 删除 + arrivalNoticeMapper.deleteById(id); + } + + @Override + public MesWmArrivalNoticeDO getArrivalNotice(Long id) { + return arrivalNoticeMapper.selectById(id); + } + + @Override + public PageResult getArrivalNoticePage(MesWmArrivalNoticePageReqVO pageReqVO) { + return arrivalNoticeMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitArrivalNotice(Long id) { + // 1.1 校验存在 + 草稿状态 + validateArrivalNoticeExistsAndDraft(id); + // 1.2 检查是否有行项目 + List lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_ARRIVAL_NOTICE_NO_LINE); + } + + // 2. 检查所有行的 iqcCheckFlag:如果有需要检验的行,进入待质检状态 + boolean needCheck = CollectionUtils.anyMatch(lines, + line -> Boolean.TRUE.equals(line.getIqcCheckFlag())); + if (needCheck) { + // 需要检验,进入待质检 + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO() + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus())); + return; + } + // 不需要检验,直接进入待入库 + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO() + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateArrivalNoticeWhenIqcFinish(Long id, Long lineId, Long iqcId, BigDecimal qualifiedQuantity) { + // 1.1 校验到货通知单存在 + MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id); + // 1.2 校验状态为待质检 + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus(), notice.getStatus())) { + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_QC); + } + + // 2. 更新到货通知单行:绑定 iqcId + 合格数量 + arrivalNoticeLineService.updateArrivalNoticeLineWhenIqcFinish(lineId, iqcId, qualifiedQuantity); + + // 3.1 判断是否所有需检行都已完成 + List lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id); + boolean hasUnchecked = CollectionUtils.anyMatch(lines, + line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null); + if (hasUnchecked) { + log.info("[updateArrivalNoticeWhenIqcFinish][到货通知单({}) 还有未完成检验的行,暂不更新状态]", id); + return; + } + // 3.2 所有行检验完成,更新主表状态 PENDING_QC → PENDING_RECEIPT + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO() + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus())); + } + + @Override + public void finishArrivalNotice(Long id) { + // 校验存在 + MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id); + // 校验状态:只有待入库才允许完成 + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus(), notice.getStatus())) { + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT); + } + + // 完成 + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO() + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.FINISHED.getStatus())); + } + + @Override + public List getArrivalNoticeList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return arrivalNoticeMapper.selectByIds(ids); + } + + @Override + public List getArrivalNoticeListByStatus(Integer status) { + if (status == null) { + return arrivalNoticeMapper.selectList(); + } + return arrivalNoticeMapper.selectListByStatus(status); + } + + @Override + public void validateArrivalNoticeAndLineExists(Long noticeId, Long lineId) { + // 1. 校验通知单存在 + MesWmArrivalNoticeDO notice = arrivalNoticeMapper.selectById(noticeId); + if (notice == null) { + throw exception(WM_ARRIVAL_NOTICE_NOT_EXISTS); + } + // 2.1 校验行存在 + MesWmArrivalNoticeLineDO line = arrivalNoticeLineService.getArrivalNoticeLine(lineId); + if (line == null) { + throw exception(WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS); + } + // 2.2 校验行属于该通知单 + if (ObjUtil.notEqual(line.getNoticeId(), noticeId)) { + throw exception(WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS); + } + } + + @Override + public MesWmArrivalNoticeDO validateArrivalNoticeExists(Long id) { + MesWmArrivalNoticeDO notice = arrivalNoticeMapper.selectById(id); + if (notice == null) { + throw exception(WM_ARRIVAL_NOTICE_NOT_EXISTS); + } + return notice; + } + + @Override + public MesWmArrivalNoticeDO validateArrivalNoticeExistsAndDraft(Long id) { + MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id); + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PREPARE.getStatus(), notice.getStatus())) { + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE); + } + return notice; + } + + private void validateCodeUnique(Long id, String code) { + MesWmArrivalNoticeDO notice = arrivalNoticeMapper.selectByCode(code); + if (notice == null) { + return; + } + if (ObjUtil.notEqual(id, notice.getId())) { + throw exception(WM_ARRIVAL_NOTICE_CODE_DUPLICATE); + } + } + + @Override + public Long getArrivalNoticeCountByVendorId(Long vendorId) { + return arrivalNoticeMapper.selectCountByVendorId(vendorId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeConfigService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeConfigService.java new file mode 100644 index 000000000..c69d1b6e8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeConfigService.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.service.wm.barcode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config.MesWmBarcodeConfigPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config.MesWmBarcodeConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeConfigDO; +import jakarta.validation.Valid; + +/** + * MES 条码配置 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmBarcodeConfigService { + + /** + * 创建条码配置 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createBarcodeConfig(@Valid MesWmBarcodeConfigSaveReqVO createReqVO); + + /** + * 更新条码配置 + * + * @param updateReqVO 更新信息 + */ + void updateBarcodeConfig(@Valid MesWmBarcodeConfigSaveReqVO updateReqVO); + + /** + * 删除条码配置 + * + * @param id 编号 + */ + void deleteBarcodeConfig(Long id); + + /** + * 获得条码配置 + * + * @param id 编号 + * @return 条码配置 + */ + MesWmBarcodeConfigDO getBarcodeConfig(Long id); + + /** + * 获得条码配置分页 + * + * @param pageReqVO 分页参数 + * @return 条码配置分页 + */ + PageResult getBarcodeConfigPage(MesWmBarcodeConfigPageReqVO pageReqVO); + + /** + * 根据业务类型获取条码配置 + * + * @param bizType 业务类型 + * @return 条码配置 + */ + MesWmBarcodeConfigDO getBarcodeConfigByBizType(Integer bizType); + + /** + * 校验条码配置存在(根据业务类型) + * + * @param bizType 业务类型 + * @return 条码配置 + */ + MesWmBarcodeConfigDO validateBarcodeConfigByBizType(Integer bizType); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeConfigServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeConfigServiceImpl.java new file mode 100644 index 000000000..3e7ff8673 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeConfigServiceImpl.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.module.mes.service.wm.barcode; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config.MesWmBarcodeConfigPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config.MesWmBarcodeConfigSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeConfigDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.barcode.MesWmBarcodeConfigMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 条码配置 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmBarcodeConfigServiceImpl implements MesWmBarcodeConfigService { + + @Resource + private MesWmBarcodeConfigMapper barcodeConfigMapper; + + @Resource + @Lazy + private MesWmBarcodeService barcodeService; + + @Override + public Long createBarcodeConfig(MesWmBarcodeConfigSaveReqVO createReqVO) { + // 校验业务类型唯一 + validateBarcodeConfigBizTypeUnique(null, createReqVO.getBizType()); + + // 插入 + MesWmBarcodeConfigDO config = BeanUtils.toBean(createReqVO, MesWmBarcodeConfigDO.class); + barcodeConfigMapper.insert(config); + return config.getId(); + } + + @Override + public void updateBarcodeConfig(MesWmBarcodeConfigSaveReqVO updateReqVO) { + // 校验存在 + validateBarcodeConfigExists(updateReqVO.getId()); + // 校验业务类型唯一 + validateBarcodeConfigBizTypeUnique(updateReqVO.getId(), updateReqVO.getBizType()); + + // 更新 + MesWmBarcodeConfigDO updateObj = BeanUtils.toBean(updateReqVO, MesWmBarcodeConfigDO.class); + barcodeConfigMapper.updateById(updateObj); + } + + @Override + public void deleteBarcodeConfig(Long id) { + // 校验存在 + validateBarcodeConfigExists(id); + // 校验是否有关联的条码记录 + if (barcodeService.getBarcodeCountByConfigId(id) > 0) { + throw exception(WM_BARCODE_CONFIG_HAS_BARCODE); + } + + // 删除 + barcodeConfigMapper.deleteById(id); + } + + private MesWmBarcodeConfigDO validateBarcodeConfigExists(Long id) { + MesWmBarcodeConfigDO config = barcodeConfigMapper.selectById(id); + if (config == null) { + throw exception(WM_BARCODE_CONFIG_NOT_EXISTS); + } + return config; + } + + private void validateBarcodeConfigBizTypeUnique(Long id, Integer bizType) { + MesWmBarcodeConfigDO config = barcodeConfigMapper.selectByBizType(bizType); + if (config == null) { + return; + } + if (ObjUtil.notEqual(config.getId(), id)) { + throw exception(WM_BARCODE_CONFIG_BIZ_TYPE_DUPLICATE); + } + } + + @Override + public MesWmBarcodeConfigDO getBarcodeConfig(Long id) { + return barcodeConfigMapper.selectById(id); + } + + @Override + public PageResult getBarcodeConfigPage(MesWmBarcodeConfigPageReqVO pageReqVO) { + return barcodeConfigMapper.selectPage(pageReqVO); + } + + @Override + public MesWmBarcodeConfigDO getBarcodeConfigByBizType(Integer bizType) { + return barcodeConfigMapper.selectByBizType(bizType); + } + + @Override + public MesWmBarcodeConfigDO validateBarcodeConfigByBizType(Integer bizType) { + MesWmBarcodeConfigDO config = barcodeConfigMapper.selectByBizType(bizType); + if (config == null) { + throw exception(WM_BARCODE_CONFIG_NOT_EXISTS); + } + return config; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeService.java new file mode 100644 index 000000000..a70cb3e41 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeService.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.service.wm.barcode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeDO; +import jakarta.validation.Valid; + +/** + * MES 条码清单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmBarcodeService { + + /** + * 创建条码 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createBarcode(@Valid MesWmBarcodeSaveReqVO createReqVO); + + /** + * 更新条码 + * + * @param updateReqVO 更新信息 + */ + void updateBarcode(@Valid MesWmBarcodeSaveReqVO updateReqVO); + + /** + * 删除条码 + * + * @param id 编号 + */ + void deleteBarcode(Long id); + + /** + * 获得条码 + * + * @param id 编号 + * @return 条码 + */ + MesWmBarcodeDO getBarcode(Long id); + + /** + * 获得条码分页 + * + * @param pageReqVO 分页参数 + * @return 条码分页 + */ + PageResult getBarcodePage(MesWmBarcodePageReqVO pageReqVO); + + /** + * 根据业务类型和业务编号获取条码 + * + * @param bizType 业务类型 + * @param bizId 业务编号 + * @return 条码 + */ + MesWmBarcodeDO getBarcodeByBizTypeAndBizId(Integer bizType, Long bizId); + + /** + * 自动生成条码 + * + * @param bizType 业务类型 + * @param bizId 业务编号 + * @param bizCode 业务编码 + * @param bizName 业务名称 + */ + void autoGenerateBarcode(Integer bizType, Long bizId, String bizCode, String bizName); + + /** + * 生成条码内容(供前端预览使用) + * + * @param bizType 业务类型 + * @param bizCode 业务编码 + * @return 生成的条码内容 + */ + String generateBarcodeContent(Integer bizType, String bizCode); + + /** + * 根据条码配置编号获取相关联的条码数量 + * + * @param configId 条码配置编号 + * @return 条码数量 + */ + long getBarcodeCountByConfigId(Long configId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeServiceImpl.java new file mode 100644 index 000000000..d2d826fcc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/barcode/MesWmBarcodeServiceImpl.java @@ -0,0 +1,217 @@ +package cn.iocoder.yudao.module.mes.service.wm.barcode; + +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.MesWmBarcodeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeConfigDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.barcode.MesWmBarcodeDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.barcode.MesWmBarcodeMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 条码清单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmBarcodeServiceImpl implements MesWmBarcodeService { + + @Resource + private MesWmBarcodeMapper barcodeMapper; + + @Resource + private MesWmBarcodeConfigService barcodeConfigService; + + @Override + public Long createBarcode(MesWmBarcodeSaveReqVO createReqVO) { + // 1. 校验数据 + MesWmBarcodeConfigDO config = validateBarcodeSaveData(createReqVO.getId(), + createReqVO.getBizType(), createReqVO.getBizId()); + + // 2. 生成条码内容,并校验唯一性 + String content = generateAndValidateContent(createReqVO.getId(), + createReqVO.getContent(), config.getContentFormat(), createReqVO.getBizCode()); + + // 3. 保存条码记录 + MesWmBarcodeDO barcode = BeanUtils.toBean(createReqVO, MesWmBarcodeDO.class).setContent(content) + .setConfigId(config.getId()).setFormat(config.getFormat()); + barcodeMapper.insert(barcode); + return barcode.getId(); + } + + @Override + public String generateBarcodeContent(Integer bizType, String bizCode) { + // 1.1 校验参数 + if (bizType == null) { + throw exception(BARCODE_BIZ_TYPE_NOT_EXISTS); + } + if (StrUtil.isBlank(bizCode)) { + throw exception(BARCODE_BIZ_CODE_NOT_EXISTS); + } + // 1.2 查询条码配置 + MesWmBarcodeConfigDO config = barcodeConfigService.validateBarcodeConfigByBizType(bizType); + + // 2. 生成条码内容 + return generateBarcodeContent(config.getContentFormat(), bizCode); + } + + @Override + public void updateBarcode(MesWmBarcodeSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateBarcodeExists(updateReqVO.getId()); + // 1.2 校验数据 + MesWmBarcodeConfigDO config = validateBarcodeSaveData(updateReqVO.getId(), + updateReqVO.getBizType(), updateReqVO.getBizId()); + + // 2. 生成条码内容,并校验唯一性 + String content = generateAndValidateContent(updateReqVO.getId(), + updateReqVO.getContent(), config.getContentFormat(), updateReqVO.getBizCode()); + + // 3. 更新(刷新 configId 和 format,确保与最新配置一致) + MesWmBarcodeDO updateObj = BeanUtils.toBean(updateReqVO, MesWmBarcodeDO.class) + .setConfigId(config.getId()).setFormat(config.getFormat()); + if (StrUtil.isNotBlank(content)) { + updateObj.setContent(content); + } + barcodeMapper.updateById(updateObj); + } + + /** + * 校验条码保存数据:条码配置 + 业务对象唯一性 + * + * @param id 条码编号(新增时为 null) + * @param bizType 业务类型 + * @param bizId 业务编号 + * @return 条码配置 + */ + private MesWmBarcodeConfigDO validateBarcodeSaveData(Long id, Integer bizType, Long bizId) { + // 1. 校验条码配置 + MesWmBarcodeConfigDO config = barcodeConfigService.validateBarcodeConfigByBizType(bizType); + // 2. 校验业务对象唯一性 + validateBarcodeUnique(id, bizType, bizId); + return config; + } + + /** + * 校验业务对象(bizType + bizId)唯一性 + * + * @param id 条码编号(新增时为 null,更新时排除自身) + * @param bizType 业务类型 + * @param bizId 业务编号 + */ + private void validateBarcodeUnique(Long id, Integer bizType, Long bizId) { + MesWmBarcodeDO barcode = barcodeMapper.selectByBizTypeAndBizId(bizType, bizId); + if (barcode == null) { + return; + } + if (ObjUtil.notEqual(barcode, id)) { + throw exception(WM_BARCODE_ALREADY_EXISTS); + } + } + + /** + * 生成条码内容(如果前端未传递则自动生成),并校验内容唯一性 + * + * @param id 条码编号(新增时为 null,更新时排除自身) + * @param content 前端传递的条码内容(可为空) + * @param contentFormat 内容格式模板 + * @param bizCode 业务编码 + * @return 最终条码内容 + */ + private String generateAndValidateContent(Long id, String content, String contentFormat, String bizCode) { + // 1. 如果前端未传递内容,则自动生成 + if (StrUtil.isBlank(content)) { + content = generateBarcodeContent(contentFormat, bizCode); + } + // 2. 校验条码内容唯一性(排除自身) + if (StrUtil.isNotBlank(content)) { + MesWmBarcodeDO contentBarcode = barcodeMapper.selectByContent(content); + if (contentBarcode != null && ObjUtil.notEqual(contentBarcode.getId(), id)) { + throw exception(WM_BARCODE_CONTENT_DUPLICATE); + } + } + return content; + } + + /** + * 生成条码内容 + * + * @param contentFormat 内容格式模板 + * @param bizCode 业务编码 + * @return 条码内容 + */ + private String generateBarcodeContent(String contentFormat, String bizCode) { + if (StrUtil.isBlank(contentFormat)) { + return bizCode; + } + return contentFormat.replace(MesWmBarcodeConfigDO.PLACEHOLDER_BUSINESS_CODE, bizCode); + } + + @Override + public void deleteBarcode(Long id) { + // 校验存在 + validateBarcodeExists(id); + // 删除 + barcodeMapper.deleteById(id); + } + + private MesWmBarcodeDO validateBarcodeExists(Long id) { + MesWmBarcodeDO barcode = barcodeMapper.selectById(id); + if (barcode == null) { + throw exception(WM_BARCODE_NOT_EXISTS); + } + return barcode; + } + + @Override + public MesWmBarcodeDO getBarcode(Long id) { + return barcodeMapper.selectById(id); + } + + @Override + public PageResult getBarcodePage(MesWmBarcodePageReqVO pageReqVO) { + return barcodeMapper.selectPage(pageReqVO); + } + + @Override + public MesWmBarcodeDO getBarcodeByBizTypeAndBizId(Integer bizType, Long bizId) { + return barcodeMapper.selectByBizTypeAndBizId(bizType, bizId); + } + + @Override + public void autoGenerateBarcode(Integer bizType, Long bizId, String bizCode, String bizName) { + // 1.1 检查是否配置自动生成 + MesWmBarcodeConfigDO config = barcodeConfigService.getBarcodeConfigByBizType(bizType); + if (config == null || Boolean.FALSE.equals(config.getAutoGenerateFlag()) + || CommonStatusEnum.isDisable(config.getStatus())) { + return; + } + // 1.2 检查是否已存在条码 + MesWmBarcodeDO existBarcode = barcodeMapper.selectByBizTypeAndBizId(bizType, bizId); + if (existBarcode != null) { + return; + } + + // 2. 创建条码记录 + MesWmBarcodeSaveReqVO createReqVO = new MesWmBarcodeSaveReqVO() + .setBizType(bizType).setBizId(bizId).setBizCode(bizCode).setBizName(bizName) + .setStatus(CommonStatusEnum.ENABLE.getStatus()); + createBarcode(createReqVO); + } + + @Override + public long getBarcodeCountByConfigId(Long configId) { + return barcodeMapper.selectCountByConfigId(configId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchService.java new file mode 100644 index 000000000..2fafc2568 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchService.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.mes.service.wm.batch; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; + +import java.util.List; + +/** + * 批次管理 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmBatchService { + + /** + * 获得批次分页 + * + * @param pageReqVO 分页查询 + * @return 批次分页 + */ + PageResult getBatchPage(MesWmBatchPageReqVO pageReqVO); + + /** + * 获得批次 + * + * @param id 批次编号 + * @return 批次记录 + */ + MesWmBatchDO getBatch(Long id); + + /** + * 根据批次号获得批次 + * + * @param code 批次号 + * @return 批次记录 + */ + MesWmBatchDO getBatchByCode(String code); + + /** + * 获取或生成批次编码 + *

+ * 根据物料批次配置,查询或生成批次记录 + * + * @param reqVO 批次参数(包含 itemId 及其他可选属性) + * @return 批次记录(如果物料未启用批次管理则返回 null) + */ + MesWmBatchDO getOrGenerateBatchCode(MesWmBatchGenerateReqVO reqVO); + + /** + * 批次向前追溯(递归查询) + *

+ * 查询当前批次被哪些工单的哪些批次产品消耗 + * + * @param code 批次编码 + * @return 批次列表 + */ + List getForwardBatchList(String code); + + /** + * 批次向后追溯(递归查询) + *

+ * 查询当前批次的产品使用了哪些批次的物资 + * + * @param code 批次编码 + * @return 批次列表 + */ + List getBackwardBatchList(String code); + + /** + * 获取批次列表 + * + * @return 批次列表 + */ + List getBatchList(); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java new file mode 100644 index 000000000..b3a2df1d8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java @@ -0,0 +1,244 @@ +package cn.iocoder.yudao.module.mes.service.wm.batch; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.batch.MesWmBatchMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemBatchConfigService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * 批次管理 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class MesWmBatchServiceImpl implements MesWmBatchService { + + @Resource + private MesWmBatchMapper batchMapper; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdItemBatchConfigService itemBatchConfigService; + @Resource + private MesMdAutoCodeRecordService autoCodeRecordService; + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public PageResult getBatchPage(MesWmBatchPageReqVO pageReqVO) { + return batchMapper.selectPage(pageReqVO); + } + + @Override + public MesWmBatchDO getBatch(Long id) { + return batchMapper.selectById(id); + } + + @Override + public MesWmBatchDO getBatchByCode(String code) { + return batchMapper.selectByCode(code); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MesWmBatchDO getOrGenerateBatchCode(MesWmBatchGenerateReqVO reqVO) { + // 1.1 查询物料信息,检查是否启用批次管理 + MesMdItemDO item = itemService.validateItemExists(reqVO.getItemId()); + if (Boolean.FALSE.equals(item.getBatchFlag())) { + // 未启用批次管理,返回 null + return null; + } + // 1.2 查询物料批次配置 + MesMdItemBatchConfigDO config = itemBatchConfigService.validateItemBatchConfigExists(reqVO.getItemId()); + + // 2. 根据配置校验必填参数并清空不需要的参数 + MesWmBatchDO batch = MesWmBatchDO.builder().itemId(reqVO.getItemId()).build(); + // 生产日期 + if (Boolean.TRUE.equals(config.getProduceDateFlag())) { + if (ObjUtil.isNull(reqVO.getProduceDate())) { + throw exception(WM_BATCH_PRODUCE_DATE_REQUIRED); + } + batch.setProduceDate(reqVO.getProduceDate()); + } + // 入库日期 + if (Boolean.TRUE.equals(config.getReceiptDateFlag())) { + if (ObjUtil.isNull(reqVO.getReceiptDate())) { + throw exception(WM_BATCH_RECEIPT_DATE_REQUIRED); + } + batch.setReceiptDate(reqVO.getReceiptDate()); + } + // 有效期 + if (Boolean.TRUE.equals(config.getExpireDateFlag())) { + if (ObjUtil.isNull(reqVO.getExpireDate())) { + throw exception(WM_BATCH_EXPIRE_DATE_REQUIRED); + } + batch.setExpireDate(reqVO.getExpireDate()); + } + // 供应商 + if (Boolean.TRUE.equals(config.getVendorFlag())) { + if (ObjUtil.isNull(reqVO.getVendorId())) { + throw exception(WM_BATCH_VENDOR_REQUIRED); + } + batch.setVendorId(reqVO.getVendorId()); + } + // 客户 + if (Boolean.TRUE.equals(config.getClientFlag())) { + if (ObjUtil.isNull(reqVO.getClientId())) { + throw exception(WM_BATCH_CLIENT_REQUIRED); + } + batch.setClientId(reqVO.getClientId()); + } + // 采购订单编号 + if (Boolean.TRUE.equals(config.getPurchaseOrderCodeFlag())) { + if (ObjUtil.isNull(reqVO.getPurchaseOrderCode())) { + throw exception(WM_BATCH_PURCHASE_ORDER_CODE_REQUIRED); + } + batch.setPurchaseOrderCode(reqVO.getPurchaseOrderCode()); + } + // 销售订单编号 + if (Boolean.TRUE.equals(config.getSalesOrderCodeFlag())) { + if (ObjUtil.isNull(reqVO.getSalesOrderCode())) { + throw exception(WM_BATCH_CUSTOMER_ORDER_CODE_REQUIRED); + } + batch.setSalesOrderCode(reqVO.getSalesOrderCode()); + } + // 生产工单 + if (Boolean.TRUE.equals(config.getWorkOrderFlag())) { + if (ObjUtil.isNull(reqVO.getWorkOrderId())) { + throw exception(WM_BATCH_WORK_ORDER_REQUIRED); + } + batch.setWorkOrderId(reqVO.getWorkOrderId()); + } + // 生产任务 + if (Boolean.TRUE.equals(config.getTaskFlag())) { + if (ObjUtil.isNull(reqVO.getTaskId())) { + throw exception(WM_BATCH_TASK_REQUIRED); + } + batch.setTaskId(reqVO.getTaskId()); + } + // 工作站 + if (Boolean.TRUE.equals(config.getWorkstationFlag())) { + if (ObjUtil.isNull(reqVO.getWorkstationId())) { + throw exception(WM_BATCH_WORKSTATION_REQUIRED); + } + batch.setWorkstationId(reqVO.getWorkstationId()); + } + // 工具 + if (Boolean.TRUE.equals(config.getToolFlag())) { + if (ObjUtil.isNull(reqVO.getToolId())) { + throw exception(WM_BATCH_TOOL_REQUIRED); + } + batch.setToolId(reqVO.getToolId()); + } + // 模具 + if (Boolean.TRUE.equals(config.getMoldFlag())) { + if (ObjUtil.isNull(reqVO.getMoldId())) { + throw exception(WM_BATCH_MOLD_REQUIRED); + } + batch.setMoldId(reqVO.getMoldId()); + } + // 生产批号 + if (Boolean.TRUE.equals(config.getLotNumberFlag())) { + if (ObjUtil.isNull(reqVO.getLotNumber())) { + throw exception(WM_BATCH_LOT_NUMBER_REQUIRED); + } + batch.setLotNumber(reqVO.getLotNumber()); + } + // 质量状态 + if (Boolean.TRUE.equals(config.getQualityStatusFlag())) { + if (ObjUtil.isNull(reqVO.getQualityStatus())) { + throw exception(WM_BATCH_QUALITY_STATUS_REQUIRED); + } + batch.setQualityStatus(reqVO.getQualityStatus()); + } + + // 3.1 情况一:查询是否存在匹配的批次 + MesWmBatchDO existingBatch = batchMapper.selectFirst(batch); + if (existingBatch != null) { + return existingBatch; + } + + // 3.2 情况二:生成新批次 + String batchCode = autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.WM_BATCH_CODE.getCode()); + batch.setCode(batchCode); + batchMapper.insert(batch); + + // 4. 生成条码 + barcodeService.autoGenerateBarcode(MesBizTypeConstants.WM_BATCH, batch.getId(), batch.getCode(), item.getName()); + return batch; + } + + @Override + public List getForwardBatchList(String code) { + return getForwardBatchList(code, new HashSet<>()); + } + + private List getForwardBatchList(String code, Set visited) { + if (code == null || !visited.add(code)) { + return new ArrayList<>(); + } + List list = batchMapper.selectListByForward(code); + if (CollUtil.isEmpty(list)) { + return new ArrayList<>(); + } + // 继续递归查询下游批次 + List results = new ArrayList<>(list); + for (MesWmBatchDO batch : list) { + results.addAll(getForwardBatchList(batch.getCode(), visited)); + } + return results; + } + + @Override + public List getBackwardBatchList(String code) { + return getBackwardBatchList(code, new HashSet<>()); + } + + private List getBackwardBatchList(String code, Set visited) { + if (code == null || !visited.add(code)) { + return new ArrayList<>(); + } + List list = batchMapper.selectListByBackward(code); + if (CollUtil.isEmpty(list)) { + return new ArrayList<>(); + } + // 继续递归查询上游批次 + List results = new ArrayList<>(list); + for (MesWmBatchDO batch : list) { + results.addAll(getBackwardBatchList(batch.getCode(), visited)); + } + return results; + } + + @Override + public List getBatchList() { + return batchMapper.selectList(); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeDetailService.java new file mode 100644 index 000000000..9a9b9a944 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeDetailService.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemconsume; + +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDetailDO; + +import java.util.List; + +/** + * MES 物料消耗记录明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmItemConsumeDetailService { + + /** + * 批量创建消耗明细 + * + * @param details 消耗明细列表 + */ + void createItemConsumeDetailBatch(List details); + + /** + * 查询指定消耗记录的所有明细 + * + * @param consumeId 消耗记录编号 + * @return 消耗明细列表 + */ + List getItemConsumeDetailListByConsumeId(Long consumeId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeDetailServiceImpl.java new file mode 100644 index 000000000..70843e67d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeDetailServiceImpl.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemconsume; + +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume.MesWmItemConsumeDetailMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +/** + * MES 物料消耗记录明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmItemConsumeDetailServiceImpl implements MesWmItemConsumeDetailService { + + @Resource + private MesWmItemConsumeDetailMapper itemConsumeDetailMapper; + + @Override + public void createItemConsumeDetailBatch(List details) { + itemConsumeDetailMapper.insertBatch(details); + } + + @Override + public List getItemConsumeDetailListByConsumeId(Long consumeId) { + return itemConsumeDetailMapper.selectListByConsumeId(consumeId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeLineService.java new file mode 100644 index 000000000..bccbd92cc --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeLineService.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemconsume; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume.vo.MesWmItemConsumeLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeLineDO; + +import java.util.List; + +/** + * MES 物料消耗记录行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmItemConsumeLineService { + + /** + * 批量创建消耗行 + * + * @param lines 消耗行列表 + */ + void createItemConsumeLineBatch(List lines); + + /** + * 根据报工记录编号分页查询消耗行 + * + * @param pageReqVO 分页查询参数(含 feedbackId) + * @return 消耗行分页 + */ + PageResult getItemConsumeLinePage(MesWmItemConsumeLinePageReqVO pageReqVO); + + /** + * 查询指定消耗记录的所有行 + * + * @param consumeId 消耗记录编号 + * @return 消耗行列表 + */ + List getItemConsumeLineListByConsumeId(Long consumeId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeLineServiceImpl.java new file mode 100644 index 000000000..1aacd6e51 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeLineServiceImpl.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemconsume; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume.vo.MesWmItemConsumeLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume.MesWmItemConsumeLineMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +/** + * MES 物料消耗记录行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmItemConsumeLineServiceImpl implements MesWmItemConsumeLineService { + + @Resource + private MesWmItemConsumeLineMapper itemConsumeLineMapper; + + @Resource + @Lazy + private MesWmItemConsumeService itemConsumeService; + + @Override + public void createItemConsumeLineBatch(List lines) { + itemConsumeLineMapper.insertBatch(lines); + } + + @Override + public PageResult getItemConsumeLinePage(MesWmItemConsumeLinePageReqVO pageReqVO) { + // 1. 先通过 feedbackId 找到消耗头(通过 Service 调用,不直接注入 Mapper) + MesWmItemConsumeDO consume = itemConsumeService.getByFeedbackId(pageReqVO.getFeedbackId()); + if (consume == null) { + return PageResult.empty(); + } + // 2. 分页查询消耗行 + return itemConsumeLineMapper.selectPage(pageReqVO, consume.getId()); + } + + @Override + public List getItemConsumeLineListByConsumeId(Long consumeId) { + return itemConsumeLineMapper.selectListByConsumeId(consumeId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeService.java new file mode 100644 index 000000000..305d5eceb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeService.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemconsume; + +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO; + +/** + * MES 物料消耗记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmItemConsumeService { + + /** + * 根据报工单生成物料消耗记录 + * + * 1. 查询当前工序的 BOM 物料配置 + * 2. 生成消耗单头 + 行(消耗数量 = BOM 用料比例 × 报工数量) + * + * @param feedback 报工记录 + * @return 生成的消耗记录,无 BOM 时返回 null + */ + MesWmItemConsumeDO generateItemConsume(MesProFeedbackDO feedback); + + /** + * 完成物料消耗(库存扣减) + * + * 遍历消耗明细(detail),按批次精确扣减线边库库存,更新消耗单状态为已完成 + * + * @param consumeId 消耗记录编号 + */ + void finishItemConsume(Long consumeId); + + /** + * 根据报工记录编号获取消耗记录 + * + * @param feedbackId 报工记录编号 + * @return 消耗记录,不存在返回 null + */ + MesWmItemConsumeDO getByFeedbackId(Long feedbackId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeServiceImpl.java new file mode 100644 index 000000000..1fc98f087 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeServiceImpl.java @@ -0,0 +1,203 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemconsume; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume.MesWmItemConsumeMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemConsumeStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductBomService; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_FEEDBACK_ROUTE_PROCESS_INVALID; + +/** + * MES 物料消耗记录 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmItemConsumeServiceImpl implements MesWmItemConsumeService { + + @Resource + private MesWmItemConsumeMapper itemConsumeMapper; + @Resource + private MesWmItemConsumeLineService itemConsumeLineService; + @Resource + private MesWmItemConsumeDetailService itemConsumeDetailService; + @Resource + private MesProRouteProductBomService routeProductBomService; + @Resource + private MesProRouteService routeService; + @Resource + private MesWmTransactionService wmTransactionService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + @Resource + private MesWmMaterialStockService materialStockService; + + @Override + public MesWmItemConsumeDO generateItemConsume(MesProFeedbackDO feedback) { + // 1.1 避免 routeId 等为 null 时 getRouteProductBomList 因 eqIfPresent 放宽条件导致误查 + if (feedback.getRouteId() == null || feedback.getProcessId() == null || feedback.getItemId() == null) { + throw exception(PRO_FEEDBACK_ROUTE_PROCESS_INVALID); + } + routeService.validateRouteExists(feedback.getRouteId()); + // 1.2 查询当前工序的 BOM 物料配置 + List boms = routeProductBomService.getRouteProductBomList( + feedback.getRouteId(), feedback.getProcessId(), feedback.getItemId()); + if (CollUtil.isEmpty(boms)) { + return null; + } + // 1.3 获取虚拟线边库信息 + MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode( + MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); + + // 2.1 生成消耗单头 + MesWmItemConsumeDO consume = MesWmItemConsumeDO.builder() + .workOrderId(feedback.getWorkOrderId()).taskId(feedback.getTaskId()) + .workstationId(feedback.getWorkstationId()).processId(feedback.getProcessId()) + .feedbackId(feedback.getId()).consumeDate(LocalDateTime.now()) + .status(MesWmItemConsumeStatusEnum.PREPARE.getStatus()).build(); + itemConsumeMapper.insert(consume); + // 2.2 批量生成消耗行(消耗数量 = BOM 用料比例 × 报工数量) + List lines = convertList(boms, bom -> MesWmItemConsumeLineDO.builder() + .consumeId(consume.getId()).itemId(bom.getItemId()) + .quantity(bom.getQuantity().multiply(feedback.getFeedbackQuantity())).build()); + itemConsumeLineService.createItemConsumeLineBatch(lines); + + // 3. 按线边库 FIFO 生成消耗明细 + List allDetails = new ArrayList<>(); + for (MesWmItemConsumeLineDO line : lines) { + generateDetailForLine(line, consume.getId(), + virtualWarehouse, virtualLocation, virtualArea, allDetails); + } + if (CollUtil.isNotEmpty(allDetails)) { + itemConsumeDetailService.createItemConsumeDetailBatch(allDetails); + } + return consume; + } + + /** + * 为单条消耗行按 FIFO 分配线边库批次,生成消耗明细 + * + * 规则: + * 1. 查询该物料在虚拟线边库中的库存记录,按入库时间升序(FIFO) + * 2. 依次从各批次分配,直到消耗量满足 + * 3. 如果线边库无库存或库存不足,剩余数量生成无批次明细(待后续盘库核销) + */ + private void generateDetailForLine(MesWmItemConsumeLineDO line, Long consumeId, + MesWmWarehouseDO warehouse, MesWmWarehouseLocationDO location, MesWmWarehouseAreaDO area, + List allDetails) { + // 查询该物料在线边库中的库存(按 receiptTime 升序 = FIFO;已排除 quantity = 0) + MesWmMaterialStockListReqVO stockQuery = new MesWmMaterialStockListReqVO().setItemId(line.getItemId()) + .setWarehouseId(warehouse.getId()).setLocationId(location.getId()).setAreaId(area.getId()); + List stocks = materialStockService.getMaterialStockList(stockQuery) + .stream().filter(s -> s.getQuantity().compareTo(BigDecimal.ZERO) > 0).toList(); + + if (CollUtil.isEmpty(stocks)) { + // 线边库无该物料库存 → 生成不带批次的明细 + allDetails.add(buildDetail(consumeId, line.getId(), null, line.getItemId(), + line.getQuantity(), null, null, warehouse, location, area)); + return; + } + + // 按 FIFO 依次从各批次分配 + BigDecimal remaining = line.getQuantity(); + for (MesWmMaterialStockDO stock : stocks) { + if (remaining.compareTo(BigDecimal.ZERO) <= 0) { + break; + } + BigDecimal allocate = stock.getQuantity().min(remaining); + allDetails.add(buildDetail(consumeId, line.getId(), stock.getId(), line.getItemId(), + allocate, stock.getBatchId(), stock.getBatchCode(), warehouse, location, area)); + remaining = remaining.subtract(allocate); + } + + // 库存不足时,剩余数量生成无批次明细(待后续盘库手工核销) + if (remaining.compareTo(BigDecimal.ZERO) > 0) { + allDetails.add(buildDetail(consumeId, line.getId(), null, line.getItemId(), + remaining, null, null, warehouse, location, area)); + } + } + + private static MesWmItemConsumeDetailDO buildDetail(Long consumeId, Long lineId, Long materialStockId, + Long itemId, BigDecimal quantity, + Long batchId, String batchCode, + MesWmWarehouseDO warehouse, + MesWmWarehouseLocationDO location, + MesWmWarehouseAreaDO area) { + return MesWmItemConsumeDetailDO.builder() + .consumeId(consumeId).lineId(lineId).materialStockId(materialStockId) + .itemId(itemId).quantity(quantity) + .batchId(batchId).batchCode(batchCode) + .warehouseId(warehouse.getId()).locationId(location.getId()).areaId(area.getId()) + .build(); + } + + @Override + public void finishItemConsume(Long consumeId) { + // 1. 查询消耗明细(detail 级别,包含精确的批次/仓库信息) + List details = itemConsumeDetailService + .getItemConsumeDetailListByConsumeId(consumeId); + + // 2. 遍历明细,创建库存事务(按批次精确扣减线边库) + for (MesWmItemConsumeDetailDO detail : details) { + wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.OUT.getType()) + .setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity().negate()) + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) + .setWarehouseId(detail.getWarehouseId()) + .setLocationId(detail.getLocationId()) + .setAreaId(detail.getAreaId()) + .setCheckFlag(false) // 线边库允许负库存 + .setBizType(MesBizTypeConstants.WM_ITEM_CONSUME) + .setBizId(consumeId) + .setBizCode("") + .setBizLineId(detail.getLineId())); + } + + // 3. 更新消耗单状态为已完成 + itemConsumeMapper.updateById(MesWmItemConsumeDO.builder() + .id(consumeId).status(MesWmItemConsumeStatusEnum.FINISHED.getStatus()).build()); + } + + @Override + public MesWmItemConsumeDO getByFeedbackId(Long feedbackId) { + return itemConsumeMapper.selectByFeedbackId(feedbackId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailService.java new file mode 100644 index 000000000..cbf8e976e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailService.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemreceipt; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 采购入库明细 Service 接口 + */ +public interface MesWmItemReceiptDetailService { + + /** + * 创建采购入库明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createItemReceiptDetail(@Valid MesWmItemReceiptDetailSaveReqVO createReqVO); + + /** + * 修改采购入库明细 + * + * @param updateReqVO 修改信息 + */ + void updateItemReceiptDetail(@Valid MesWmItemReceiptDetailSaveReqVO updateReqVO); + + /** + * 删除采购入库明细 + * + * @param id 编号 + */ + void deleteItemReceiptDetail(Long id); + + /** + * 获得采购入库明细 + * + * @param id 编号 + * @return 采购入库明细 + */ + MesWmItemReceiptDetailDO getItemReceiptDetail(Long id); + + /** + * 按入库单编号获得明细列表 + * + * @param receiptId 入库单编号 + * @return 明细列表 + */ + List getItemReceiptDetailListByReceiptId(Long receiptId); + + /** + * 按入库单行编号获得明细列表 + * + * @param lineId 行编号 + * @return 明细列表 + */ + List getItemReceiptDetailListByLineId(Long lineId); + + /** + * 按入库单行编号批量删除明细 + * + * @param lineId 行编号 + */ + void deleteItemReceiptDetailByLineId(Long lineId); + + /** + * 按入库单编号批量删除明细 + * + * @param receiptId 入库单编号 + */ + void deleteItemReceiptDetailByReceiptId(Long receiptId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailServiceImpl.java new file mode 100644 index 000000000..1d187f586 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailServiceImpl.java @@ -0,0 +1,148 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemreceipt; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptDetailMapper; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 采购入库明细 Service 实现类 + */ +@Service +@Validated +public class MesWmItemReceiptDetailServiceImpl implements MesWmItemReceiptDetailService { + + @Resource + private MesWmItemReceiptDetailMapper itemReceiptDetailMapper; + + @Resource + @Lazy + private MesWmItemReceiptService itemReceiptService; + + @Resource + @Lazy + private MesWmItemReceiptLineService itemReceiptLineService; + + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + @Resource + @Lazy + private MesWmMaterialStockService materialStockService; + + @Override + public Long createItemReceiptDetail(MesWmItemReceiptDetailSaveReqVO createReqVO) { + // 1. 校验数据 + itemReceiptService.validateItemReceiptEditable(createReqVO.getReceiptId()); + validateItemReceiptDetailSaveData(createReqVO); + + // 2. 插入 + MesWmItemReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmItemReceiptDetailDO.class); + itemReceiptDetailMapper.insert(detail); + + // 3. 插入后校验数量是否超出 + validateDetailQuantityNotExceed(createReqVO.getLineId()); + return detail.getId(); + } + + @Override + public void updateItemReceiptDetail(MesWmItemReceiptDetailSaveReqVO updateReqVO) { + // 1.1 校验存在 + MesWmItemReceiptDetailDO detail = validateItemReceiptDetailExists(updateReqVO.getId()); + // 1.2 校验数据 + updateReqVO.setReceiptId(detail.getReceiptId()); + validateItemReceiptDetailSaveData(updateReqVO); + + // 2. 更新 + MesWmItemReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmItemReceiptDetailDO.class); + itemReceiptDetailMapper.updateById(updateObj); + + // 3. 更新后校验数量是否超出 + validateDetailQuantityNotExceed(detail.getLineId()); + } + + private void validateItemReceiptDetailSaveData(MesWmItemReceiptDetailSaveReqVO reqVO) { + // 校验父单据存在且为可编辑状态 + itemReceiptService.validateItemReceiptEditable(reqVO.getReceiptId()); + // 校验库区关系 + warehouseAreaService.validateWarehouseAreaExists(reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); + // 校验库位物料/批次混放规则 + materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId()); + } + + @Override + public void deleteItemReceiptDetail(Long id) { + // 1.1 校验存在 + MesWmItemReceiptDetailDO detail = validateItemReceiptDetailExists(id); + // 1.2 校验父单据存在且为可编辑状态 + itemReceiptService.validateItemReceiptEditable(detail.getReceiptId()); + + // 删除 + itemReceiptDetailMapper.deleteById(id); + } + + @Override + public MesWmItemReceiptDetailDO getItemReceiptDetail(Long id) { + return itemReceiptDetailMapper.selectById(id); + } + + @Override + public List getItemReceiptDetailListByReceiptId(Long receiptId) { + return itemReceiptDetailMapper.selectListByReceiptId(receiptId); + } + + @Override + public List getItemReceiptDetailListByLineId(Long lineId) { + return itemReceiptDetailMapper.selectListByLineId(lineId); + } + + @Override + public void deleteItemReceiptDetailByLineId(Long lineId) { + itemReceiptDetailMapper.deleteByLineId(lineId); + } + + @Override + public void deleteItemReceiptDetailByReceiptId(Long receiptId) { + itemReceiptDetailMapper.deleteByReceiptId(receiptId); + } + + private MesWmItemReceiptDetailDO validateItemReceiptDetailExists(Long id) { + MesWmItemReceiptDetailDO detail = itemReceiptDetailMapper.selectById(id); + if (detail == null) { + throw exception(WM_ITEM_RECEIPT_DETAIL_NOT_EXISTS); + } + return detail; + } + + /** + * 校验行下所有明细的数量之和不超过行的入库数量 + * + * @param lineId 行编号 + */ + private void validateDetailQuantityNotExceed(Long lineId) { + MesWmItemReceiptLineDO line = itemReceiptLineService.getItemReceiptLine(lineId); + if (line == null || line.getReceivedQuantity() == null) { + return; + } + List details = itemReceiptDetailMapper.selectListByLineId(lineId); + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmItemReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (totalDetailQty.compareTo(line.getReceivedQuantity()) > 0) { + throw exception(WM_ITEM_RECEIPT_DETAIL_QUANTITY_EXCEED); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineService.java new file mode 100644 index 000000000..26a790bc5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineService.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 采购入库单行 Service 接口 + */ +public interface MesWmItemReceiptLineService { + + /** + * 创建采购入库单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createItemReceiptLine(@Valid MesWmItemReceiptLineSaveReqVO createReqVO); + + /** + * 修改采购入库单行 + * + * @param updateReqVO 修改信息 + */ + void updateItemReceiptLine(@Valid MesWmItemReceiptLineSaveReqVO updateReqVO); + + /** + * 删除采购入库单行(级联删除明细) + * + * @param id 编号 + */ + void deleteItemReceiptLine(Long id); + + /** + * 获得采购入库单行 + * + * @param id 编号 + * @return 采购入库单行 + */ + MesWmItemReceiptLineDO getItemReceiptLine(Long id); + + /** + * 获得采购入库单行分页 + * + * @param pageReqVO 分页参数 + * @return 采购入库单行分页 + */ + PageResult getItemReceiptLinePage(MesWmItemReceiptLinePageReqVO pageReqVO); + + /** + * 按入库单编号获得行列表 + * + * @param receiptId 入库单编号 + * @return 行列表 + */ + List getItemReceiptLineListByReceiptId(Long receiptId); + + /** + * 按入库单编号批量删除行 + * + * @param receiptId 入库单编号 + */ + void deleteItemReceiptLineByReceiptId(Long receiptId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java new file mode 100644 index 000000000..cf906b689 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java @@ -0,0 +1,188 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptLineMapper; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeLineService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 采购入库单行 Service 实现类 + */ +@Service +@Validated +public class MesWmItemReceiptLineServiceImpl implements MesWmItemReceiptLineService { + + @Resource + private MesWmItemReceiptLineMapper itemReceiptLineMapper; + + @Resource + @Lazy + private MesWmItemReceiptService itemReceiptService; + @Resource + private MesWmItemReceiptDetailService itemReceiptDetailService; + @Resource + @Lazy + private MesWmArrivalNoticeLineService arrivalNoticeLineService; + @Resource + private MesWmBatchService batchService; + + @Override + public Long createItemReceiptLine(MesWmItemReceiptLineSaveReqVO createReqVO) { + // 1. 校验父单据存在且为可编辑状态 + MesWmItemReceiptDO receipt = itemReceiptService.validateItemReceiptEditable(createReqVO.getReceiptId()); + // 2. 校验数据 + validateItemReceiptLineSaveData(receipt, createReqVO); + + // 3.1 创建入库单行 + MesWmItemReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmItemReceiptLineDO.class); + // 3.2 生成或获取批次 + MesWmBatchDO batch = generateOrGetBatch(receipt, createReqVO); + if (batch != null) { + line.setBatchId(batch.getId()); + line.setBatchCode(batch.getCode()); + } + // 3.3 插入数据库 + itemReceiptLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateItemReceiptLine(MesWmItemReceiptLineSaveReqVO updateReqVO) { + // 1.1 校验存在 + MesWmItemReceiptLineDO line = validateItemReceiptLineExists(updateReqVO.getId()); + // 1.2 校验父单据存在且为可编辑状态 + MesWmItemReceiptDO receipt = itemReceiptService.validateItemReceiptEditable(line.getReceiptId()); + // 1.3 校验数据 + validateItemReceiptLineSaveData(receipt, updateReqVO); + + // 2.1 更新 + MesWmItemReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmItemReceiptLineDO.class); + // 2.2 生成或获取批次 + MesWmBatchDO batch = generateOrGetBatch(receipt, updateReqVO); + if (batch != null) { + updateObj.setBatchId(batch.getId()).setBatchCode(batch.getCode()); + } + // 2.3 更新数据库 + itemReceiptLineMapper.updateById(updateObj); + } + + private void validateItemReceiptLineSaveData(MesWmItemReceiptDO receipt, MesWmItemReceiptLineSaveReqVO reqVO) { + // 校验关联到货通知单行 + validateArrivalNoticeLine(receipt, reqVO.getArrivalNoticeLineId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteItemReceiptLine(Long id) { + // 1.1 校验存在 + MesWmItemReceiptLineDO line = validateItemReceiptLineExists(id); + // 1.2 校验父单据存在且为可编辑状态 + itemReceiptService.validateItemReceiptEditable(line.getReceiptId()); + + // 2.1 级联删除明细 + itemReceiptDetailService.deleteItemReceiptDetailByLineId(id); + // 2.2 删除 + itemReceiptLineMapper.deleteById(id); + } + + @Override + public MesWmItemReceiptLineDO getItemReceiptLine(Long id) { + return itemReceiptLineMapper.selectById(id); + } + + @Override + public PageResult getItemReceiptLinePage(MesWmItemReceiptLinePageReqVO pageReqVO) { + // 如果传了 vendorId,先查出该供应商的所有入库单 ID,设置到 receiptIds + if (pageReqVO.getReceiptId() == null) { + List receipts = itemReceiptService.getItemReceiptListByVendorId(pageReqVO.getVendorId()); + if (CollUtil.isEmpty(receipts)) { + return PageResult.empty(); + } + pageReqVO.setReceiptIds(convertList(receipts, MesWmItemReceiptDO::getId)); + } + // 查询分页 + return itemReceiptLineMapper.selectPage(pageReqVO); + } + + @Override + public List getItemReceiptLineListByReceiptId(Long receiptId) { + return itemReceiptLineMapper.selectListByReceiptId(receiptId); + } + + @Override + public void deleteItemReceiptLineByReceiptId(Long receiptId) { + itemReceiptLineMapper.deleteByReceiptId(receiptId); + } + + /** + * 校验到货通知单行 + * + * @param receipt 入库单 + * @param arrivalNoticeLineId 到货通知单行编号 + */ + private void validateArrivalNoticeLine(MesWmItemReceiptDO receipt, Long arrivalNoticeLineId) { + // 情况一:如果入库单关联了到货通知单,则必须关联到货通知单行 + if (receipt.getNoticeId() != null) { + if (arrivalNoticeLineId == null) { + throw exception(WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_REQUIRED); + } + arrivalNoticeLineService.validateArrivalNoticeLineExists( + arrivalNoticeLineId, receipt.getNoticeId()); + return; + } + + // 情况二:如果入库单没有关联到货通知单,则不允许关联到货通知单行 + if (arrivalNoticeLineId != null) { + throw exception(WM_ITEM_RECEIPT_LINE_ARRIVAL_NOTICE_LINE_NOT_ALLOWED); + } + } + + private MesWmItemReceiptLineDO validateItemReceiptLineExists(Long id) { + MesWmItemReceiptLineDO line = itemReceiptLineMapper.selectById(id); + if (line == null) { + throw exception(WM_ITEM_RECEIPT_LINE_NOT_EXISTS); + } + return line; + } + + /** + * 生成或获取批次 + * + * @param receipt 入库单 + * @param reqVO 入库单行请求VO + * @return 批次记录(如果物料未启用批次管理则返回 null) + */ + private MesWmBatchDO generateOrGetBatch(MesWmItemReceiptDO receipt, MesWmItemReceiptLineSaveReqVO reqVO) { + // 构建批次参数 VO + MesWmBatchGenerateReqVO batchReqVO = new MesWmBatchGenerateReqVO(); + // 从入库单行获取 + batchReqVO.setItemId(reqVO.getItemId()).setProduceDate(reqVO.getProductionDate()) + .setExpireDate(reqVO.getExpireDate()).setLotNumber(reqVO.getLotNumber()); + // 从父单据获取 + batchReqVO.setVendorId(receipt.getVendorId()).setReceiptDate(receipt.getReceiptDate()) + .setPurchaseOrderCode(receipt.getPurchaseOrderCode()); + + // 生成或获取批次 + return batchService.getOrGenerateBatchCode(batchReqVO); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java new file mode 100644 index 000000000..17bc00eb9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 采购入库单 Service 接口 + */ +public interface MesWmItemReceiptService { + + /** + * 创建采购入库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createItemReceipt(@Valid MesWmItemReceiptSaveReqVO createReqVO); + + /** + * 修改采购入库单 + * + * @param updateReqVO 修改信息 + */ + void updateItemReceipt(@Valid MesWmItemReceiptSaveReqVO updateReqVO); + + /** + * 删除采购入库单(级联删除行+明细) + * + * @param id 编号 + */ + void deleteItemReceipt(Long id); + + /** + * 获得采购入库单 + * + * @param id 编号 + * @return 采购入库单 + */ + MesWmItemReceiptDO getItemReceipt(Long id); + + /** + * 获得采购入库单分页 + * + * @param pageReqVO 分页参数 + * @return 采购入库单分页 + */ + PageResult getItemReceiptPage(MesWmItemReceiptPageReqVO pageReqVO); + + /** + * 提交采购入库单(草稿 → 待上架) + * + * @param id 编号 + */ + void submitItemReceipt(Long id); + + /** + * 执行上架(待上架 → 待入库) + * + * @param id 编号 + */ + void stockItemReceipt(Long id); + + /** + * 执行入库(待入库 → 已完成),更新库存台账 + * + * @param id 编号 + */ + void finishItemReceipt(Long id); + + /** + * 取消采购入库单(任意非已完成/已取消状态 → 已取消) + * + * @param id 编号 + */ + void cancelItemReceipt(Long id); + + /** + * 校验采购入库单存在且处于可编辑状态(草稿或待上架) + * + * @param id 编号 + * @return 采购入库单 + */ + MesWmItemReceiptDO validateItemReceiptEditable(Long id); + + /** + * 查询指定供应商的采购入库单数量 + * + * @param vendorId 供应商编号 + * @return 数量 + */ + Long getItemReceiptCountByVendorId(Long vendorId); + + /** + * 查询指定供应商的采购入库单列表 + * + * @param vendorId 供应商编号 + * @return 入库单列表 + */ + List getItemReceiptListByVendorId(Long vendorId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java new file mode 100644 index 000000000..6690cb798 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java @@ -0,0 +1,266 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 采购入库单 Service 实现类 + */ +@Service +@Validated +public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService { + + @Resource + private MesWmItemReceiptMapper itemReceiptMapper; + + @Resource + private MesWmItemReceiptLineService itemReceiptLineService; + @Resource + private MesWmItemReceiptDetailService itemReceiptDetailService; + @Resource + @Lazy + private MesWmArrivalNoticeService arrivalNoticeService; + @Resource + private MesMdVendorService vendorService; + @Resource + @Lazy + private MesQcIqcService iqcService; + + @Resource + private MesWmTransactionService wmTransactionService; + + @Override + public Long createItemReceipt(MesWmItemReceiptSaveReqVO createReqVO) { + // 校验数据 + validateItemReceiptSaveData(createReqVO); + + // 插入 + MesWmItemReceiptDO receipt = BeanUtils.toBean(createReqVO, MesWmItemReceiptDO.class); + receipt.setStatus(MesWmItemReceiptStatusEnum.PREPARE.getStatus()); + itemReceiptMapper.insert(receipt); + return receipt.getId(); + } + + @Override + public void updateItemReceipt(MesWmItemReceiptSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateItemReceiptExistsAndDraft(updateReqVO.getId()); + // 校验数据 + validateItemReceiptSaveData(updateReqVO); + + // 更新 + MesWmItemReceiptDO updateObj = BeanUtils.toBean(updateReqVO, MesWmItemReceiptDO.class); + itemReceiptMapper.updateById(updateObj); + } + + private void validateItemReceiptSaveData(MesWmItemReceiptSaveReqVO reqVO) { + // 校验编码唯一 + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验供应商存在 + vendorService.validateVendorExists(reqVO.getVendorId()); + // 校验到货通知单存在 + if (reqVO.getNoticeId() != null) { + arrivalNoticeService.validateArrivalNoticeExists(reqVO.getNoticeId()); + } + // 校验来料检验单存在 + if (reqVO.getIqcId() != null) { + iqcService.validateIqcExists(reqVO.getIqcId()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteItemReceipt(Long id) { + // 校验存在 + 草稿状态 + validateItemReceiptExistsAndDraft(id); + + // 级联删除明细和行 + itemReceiptDetailService.deleteItemReceiptDetailByReceiptId(id); + itemReceiptLineService.deleteItemReceiptLineByReceiptId(id); + // 删除 + itemReceiptMapper.deleteById(id); + } + + @Override + public MesWmItemReceiptDO getItemReceipt(Long id) { + return itemReceiptMapper.selectById(id); + } + + @Override + public PageResult getItemReceiptPage(MesWmItemReceiptPageReqVO pageReqVO) { + return itemReceiptMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitItemReceipt(Long id) { + // 校验存在 + 草稿状态 + validateItemReceiptExistsAndDraft(id); + // 校验至少有一条行 + List lines = itemReceiptLineService.getItemReceiptLineListByReceiptId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_ITEM_RECEIPT_NO_LINE); + } + + // 提交(草稿 → 待上架) + itemReceiptMapper.updateById(new MesWmItemReceiptDO() + .setId(id).setStatus(MesWmItemReceiptStatusEnum.APPROVING.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockItemReceipt(Long id) { + // 校验存在 + MesWmItemReceiptDO receipt = validateItemReceiptExists(id); + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus())) { + throw exception(WM_ITEM_RECEIPT_STATUS_ERROR); + } + // 校验每行明细数量之和是否等于行入库数量 + List lines = itemReceiptLineService.getItemReceiptLineListByReceiptId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_ITEM_RECEIPT_NO_LINE); + } + for (MesWmItemReceiptLineDO line : lines) { + List details = itemReceiptDetailService.getItemReceiptDetailListByLineId(line.getId()); + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmItemReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (line.getReceivedQuantity() == null || totalDetailQty.compareTo(line.getReceivedQuantity()) != 0) { + throw exception(WM_ITEM_RECEIPT_DETAIL_QUANTITY_MISMATCH); + } + } + + // 执行上架(待上架 → 待入库) + itemReceiptMapper.updateById(new MesWmItemReceiptDO() + .setId(id).setStatus(MesWmItemReceiptStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishItemReceipt(Long id) { + // 1. 校验存在 + MesWmItemReceiptDO receipt = validateItemReceiptExists(id); + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.APPROVED.getStatus(), receipt.getStatus())) { + throw exception(WM_ITEM_RECEIPT_STATUS_ERROR); + } + + // 2. 遍历所有明细,创建库存事务(增加库存 + 记录流水) + createTransactionList(receipt); + + // 3. 更新入库单状态 + itemReceiptMapper.updateById(new MesWmItemReceiptDO() + .setId(id).setStatus(MesWmItemReceiptStatusEnum.FINISHED.getStatus())); + + // 4. 更新关联的到货通知单状态 + if (receipt.getNoticeId() != null) { + arrivalNoticeService.finishArrivalNotice(receipt.getNoticeId()); + } + } + + private void createTransactionList(MesWmItemReceiptDO receipt) { + List details = itemReceiptDetailService.getItemReceiptDetailListByReceiptId(receipt.getId()); + wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity()) // 入库数量为正数 + .setBatchId(detail.getBatchId()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setVendorId(receipt.getVendorId()).setReceiptTime(receipt.getReceiptDate()) + .setBizType(MesBizTypeConstants.WM_ITEM_RECEIPT_IN).setBizId(receipt.getId()) + .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId()))); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelItemReceipt(Long id) { + // 校验存在 + MesWmItemReceiptDO receipt = validateItemReceiptExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(receipt.getStatus(), + MesWmItemReceiptStatusEnum.FINISHED.getStatus(), + MesWmItemReceiptStatusEnum.CANCELED.getStatus())) { + throw exception(WM_ITEM_RECEIPT_CANCEL_NOT_ALLOWED); + } + // 取消 + itemReceiptMapper.updateById(new MesWmItemReceiptDO() + .setId(id).setStatus(MesWmItemReceiptStatusEnum.CANCELED.getStatus())); + } + + @Override + public MesWmItemReceiptDO validateItemReceiptEditable(Long id) { + MesWmItemReceiptDO receipt = validateItemReceiptExists(id); + if (ObjUtil.notEqual(receipt.getStatus(), MesWmItemReceiptStatusEnum.PREPARE.getStatus()) + && ObjUtil.notEqual(receipt.getStatus(), MesWmItemReceiptStatusEnum.APPROVING.getStatus())) { + throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE); + } + return receipt; + } + + private MesWmItemReceiptDO validateItemReceiptExists(Long id) { + MesWmItemReceiptDO receipt = itemReceiptMapper.selectById(id); + if (receipt == null) { + throw exception(WM_ITEM_RECEIPT_NOT_EXISTS); + } + return receipt; + } + + /** + * 校验采购入库单存在且为草稿状态 + */ + private MesWmItemReceiptDO validateItemReceiptExistsAndDraft(Long id) { + MesWmItemReceiptDO receipt = validateItemReceiptExists(id); + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())) { + throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE); + } + return receipt; + } + + private void validateCodeUnique(Long id, String code) { + MesWmItemReceiptDO receipt = itemReceiptMapper.selectByCode(code); + if (receipt == null) { + return; + } + if (ObjUtil.notEqual(id, receipt.getId())) { + throw exception(WM_ITEM_RECEIPT_CODE_DUPLICATE); + } + } + + @Override + public Long getItemReceiptCountByVendorId(Long vendorId) { + return itemReceiptMapper.selectCountByVendorId(vendorId); + } + + @Override + public List getItemReceiptListByVendorId(Long vendorId) { + return itemReceiptMapper.selectListByVendorId(vendorId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java new file mode 100644 index 000000000..9d02bdf59 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java @@ -0,0 +1,135 @@ +package cn.iocoder.yudao.module.mes.service.wm.materialstock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockFreezeReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; + +/** + * MES 库存台账 Service 接口 + */ +public interface MesWmMaterialStockService { + + /** + * 获得库存记录 + * + * @param id 编号 + * @return 库存记录 + */ + MesWmMaterialStockDO getMaterialStock(Long id); + + /** + * 查询指定库位的库存记录列表 + * + * @param areaId 库位编号 + * @return 库存记录列表 + */ + List getMaterialStockListByAreaId(Long areaId); + + /** + * 获得库存台账分页 + * + * @param pageReqVO 分页参数 + * @return 库存台账分页 + */ + PageResult getMaterialStockPage(MesWmMaterialStockPageReqVO pageReqVO); + + /** + * 更新库存冻结状态 + * + * @param updateReqVO 更新信息 + */ + void updateMaterialStockFrozen(@Valid MesWmMaterialStockFreezeReqVO updateReqVO); + + /** + * 批量更新库存冻结状态 + * + * @param ids 库存记录编号列表 + * @param frozen 是否冻结 + */ + void updateMaterialStockFrozen(Collection ids, boolean frozen); + + /** + * 获得仓库下库存记录数量 + * + * @param warehouseId 仓库编号 + * @return 记录数量 + */ + Long getMaterialStockCountByWarehouseId(Long warehouseId); + + /** + * 获得库区下库存记录数量 + * + * @param locationId 库区编号 + * @return 记录数量 + */ + Long getMaterialStockCountByLocationId(Long locationId); + + /** + * 获得库位下库存记录数量 + * + * @param areaId 库位编号 + * @return 记录数量 + */ + Long getMaterialStockCountByAreaId(Long areaId); + + /** + * 按编号集合获得库存记录列表 + * + * @param ids 编号集合 + * @return 库存记录列表 + */ + List getMaterialStockList(Collection ids); + + /** + * 获得物料库存列表(用于盘点等场景) + * + * @param reqVO 查询条件 + * @return 物料库存列表 + */ + List getMaterialStockList(MesWmMaterialStockListReqVO reqVO); + + /** + * 获取或创建库存记录(按组合键唯一) + * + * @param itemId 物料编号 + * @param warehouseId 仓库编号 + * @param locationId 库区编号 + * @param areaId 库位编号 + * @param batchId 批次编号 + * @param batchCode 批次号 + * @param vendorId 供应商编号 + * @param receiptTime 入库时间(为空则默认当前时间) + * @return 库存记录 + */ + MesWmMaterialStockDO getOrCreateMaterialStock(Long itemId, Long warehouseId, Long locationId, Long areaId, + Long batchId, String batchCode, Long vendorId, LocalDateTime receiptTime); + + /** + * 更新库存数量 + * + * @param id 库存记录编号 + * @param quantity 变动数量(正数=增加,负数=扣减) + * @param checkFlag 是否校验库存充足(为 true 且扣减后为负则报错) + */ + void updateMaterialStockQuantity(Long id, BigDecimal quantity, boolean checkFlag); + + /** + * 库位混放规则校验 + * + * 根据库位配置的物料和批次混放规则,检查是否允许在该库位存放指定物料/批次 + * + * @param areaId 库位编号 + * @param itemId 物料编号 + * @param batchId 批次编号(可为 null) + */ + void checkAreaMixingRule(Long areaId, Long itemId, Long batchId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java new file mode 100644 index 000000000..249b5ee2d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java @@ -0,0 +1,188 @@ +package cn.iocoder.yudao.module.mes.service.wm.materialstock; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockFreezeReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.*; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 库存台账 Service 实现类 + */ +@Service +@Validated +public class MesWmMaterialStockServiceImpl implements MesWmMaterialStockService { + + @Resource + private MesWmMaterialStockMapper materialStockMapper; + + @Resource + private MesMdItemService itemService; + @Resource + private MesMdItemTypeService itemTypeService; + @Resource + private MesWmWarehouseAreaService areaService; + + @Override + public MesWmMaterialStockDO getMaterialStock(Long id) { + return materialStockMapper.selectById(id); + } + + @Override + public List getMaterialStockListByAreaId(Long areaId) { + return materialStockMapper.selectList(MesWmMaterialStockDO::getAreaId, areaId); + } + + public MesWmMaterialStockDO validateMaterialStockExists(Long id) { + MesWmMaterialStockDO stock = materialStockMapper.selectById(id); + if (stock == null) { + throw exception(WM_MATERIAL_STOCK_NOT_EXISTS); + } + return stock; + } + + @Override + public PageResult getMaterialStockPage(MesWmMaterialStockPageReqVO pageReqVO) { + // 1.1 解析 itemTypeId:包含子分类 + Set itemTypeIds = null; + if (pageReqVO.getItemTypeId() != null) { + itemTypeIds = new HashSet<>(); + itemTypeIds.add(pageReqVO.getItemTypeId()); + List children = itemTypeService.getItemTypeChildrenList(pageReqVO.getItemTypeId()); + itemTypeIds.addAll(convertSet(children, MesMdItemTypeDO::getId)); + } + // 1.2 解析 itemId + Set itemIds = null; + if (pageReqVO.getItemId() != null) { + itemIds = SetUtils.asSet(pageReqVO.getItemId()); + } + + // 2. 分页查询 + return materialStockMapper.selectPage(pageReqVO, itemTypeIds, itemIds); + } + + @Override + public void updateMaterialStockFrozen(MesWmMaterialStockFreezeReqVO updateReqVO) { + // 校验存在 + validateMaterialStockExists(updateReqVO.getId()); + + // 更新冻结状态 + materialStockMapper.updateById(new MesWmMaterialStockDO() + .setId(updateReqVO.getId()).setFrozen(updateReqVO.getFrozen())); + } + + @Override + public void updateMaterialStockFrozen(Collection ids, boolean frozen) { + if (CollUtil.isEmpty(ids)) { + return; + } + materialStockMapper.updateByIds(ids, new MesWmMaterialStockDO().setFrozen(frozen)); + } + + @Override + public Long getMaterialStockCountByWarehouseId(Long warehouseId) { + return materialStockMapper.selectCountByWarehouseId(warehouseId); + } + + @Override + public Long getMaterialStockCountByLocationId(Long locationId) { + return materialStockMapper.selectCountByLocationId(locationId); + } + + @Override + public Long getMaterialStockCountByAreaId(Long areaId) { + return materialStockMapper.selectCountByAreaId(areaId); + } + + @Override + public List getMaterialStockList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return materialStockMapper.selectListByIds(ids); + } + + @Override + public List getMaterialStockList(MesWmMaterialStockListReqVO reqVO) { + return materialStockMapper.selectList(reqVO); + } + + @Override + public MesWmMaterialStockDO getOrCreateMaterialStock(Long itemId, Long warehouseId, Long locationId, Long areaId, + Long batchId, String batchCode, Long vendorId, LocalDateTime receiptTime) { + // 1. 查找已有库存记录 + MesWmMaterialStockDO stock = materialStockMapper.selectByCompositeKey( + itemId, warehouseId, locationId, areaId, batchId); + if (stock != null) { + return stock; + } + + // 2. 不存在则新建 + MesMdItemDO item = itemService.validateItemExists(itemId); + MesWmMaterialStockDO newStock = MesWmMaterialStockDO.builder() + .itemId(itemId).itemTypeId(item.getItemTypeId()) + .warehouseId(warehouseId).locationId(locationId).areaId(areaId) + .batchId(batchId).batchCode(batchCode).vendorId(vendorId) + .quantity(BigDecimal.ZERO) // 初始数量为 0,由 updateMaterialStockQuantity 更新 + .receiptTime(receiptTime != null ? receiptTime : LocalDateTime.now()) + .frozen(false) + .build(); + materialStockMapper.insert(newStock); + return newStock; + } + + @Override + public void updateMaterialStockQuantity(Long id, BigDecimal quantity, boolean checkFlag) { + // 更新库存数量(Mapper 层 CAS 防负库存;checkFlag=false 时允许负数) + int updatedRows = materialStockMapper.updateQuantity(id, quantity, checkFlag); + if (updatedRows == 0) { + throw exception(WM_MATERIAL_STOCK_INSUFFICIENT); + } + } + + @Override + public void checkAreaMixingRule(Long areaId, Long itemId, Long batchId) { + // 1.1 校验库位必须存在 + MesWmWarehouseAreaDO area = areaService.validateWarehouseAreaExists(areaId); + + // 2. 查询当前库位上已有的库存记录 + List stockList = getMaterialStockListByAreaId(areaId); + if (CollUtil.isEmpty(stockList)) { + return; + } + // 2.1 检查物料混放 + if (Boolean.FALSE.equals(area.getAllowItemMixing()) && itemId != null) { + if (CollUtil.anyMatch(stockList, item -> ObjUtil.notEqual(itemId, item.getItemId()))) { + throw exception(WM_MATERIAL_STOCK_AREA_ITEM_MIXING_NOT_ALLOWED, area.getName()); + } + } + // 2.2 检查批次混放 + if (Boolean.FALSE.equals(area.getAllowBatchMixing()) && batchId != null) { + if (CollUtil.anyMatch(stockList, item -> ObjUtil.notEqual(batchId, item.getBatchId()))) { + throw exception(WM_MATERIAL_STOCK_AREA_BATCH_MIXING_NOT_ALLOWED, area.getName()); + } + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueDetailService.java new file mode 100644 index 000000000..9f9b0e153 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueDetailService.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscissue; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO; + +/** + * MES 杂项出库明细 Service 接口 + */ +public interface MesWmMiscIssueDetailService { + + /** + * 创建杂项出库明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMiscIssueDetail(MesWmMiscIssueLineSaveReqVO createReqVO); + + /** + * 更新杂项出库明细 + * + * @param updateReqVO 更新信息 + */ + void updateMiscIssueDetail(MesWmMiscIssueLineSaveReqVO updateReqVO); + + /** + * 删除杂项出库明细(根据出库单ID) + * + * @param issueId 出库单ID + */ + void deleteMiscIssueDetailByIssueId(Long issueId); + + /** + * 删除杂项出库明细(根据行ID) + * + * @param lineId 行ID + */ + void deleteMiscIssueDetailByLineId(Long lineId); + + /** + * 校验杂项出库明细是否存在 + * + * @param id 编号 + */ + void validateMiscIssueDetailExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueDetailServiceImpl.java new file mode 100644 index 000000000..58d132f69 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueDetailServiceImpl.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue.MesWmMiscIssueDetailMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MISC_ISSUE_DETAIL_NOT_EXISTS; + +/** + * MES 杂项出库明细 Service 实现类 + */ +@Service +@Validated +public class MesWmMiscIssueDetailServiceImpl implements MesWmMiscIssueDetailService { + + @Resource + private MesWmMiscIssueDetailMapper issueDetailMapper; + + @Override + public Long createMiscIssueDetail(MesWmMiscIssueLineSaveReqVO createReqVO) { + MesWmMiscIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmMiscIssueDetailDO.class); + detail.setId(null); // 清空 id,让数据库自动生成 + detail.setLineId(createReqVO.getId()); // VO 的 id 就是 lineId + issueDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateMiscIssueDetail(MesWmMiscIssueLineSaveReqVO updateReqVO) { + // 基于 lineId 查询唯一的 detail 记录(VO 的 id 字段是 lineId) + List details = issueDetailMapper.selectListByLineId(updateReqVO.getId()); + if (CollUtil.isEmpty(details)) { + return; + } + + // 更新 detail(应该只有一条记录) + MesWmMiscIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscIssueDetailDO.class); + updateObj.setId(details.get(0).getId()); // 使用查询到的 detail id + updateObj.setLineId(updateReqVO.getId()); // VO 的 id 就是 lineId + issueDetailMapper.updateById(updateObj); + } + + @Override + public void deleteMiscIssueDetailByIssueId(Long issueId) { + issueDetailMapper.deleteByIssueId(issueId); + } + + @Override + public void deleteMiscIssueDetailByLineId(Long lineId) { + issueDetailMapper.deleteByLineId(lineId); + } + + @Override + public void validateMiscIssueDetailExists(Long id) { + if (issueDetailMapper.selectById(id) == null) { + throw exception(WM_MISC_ISSUE_DETAIL_NOT_EXISTS); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineService.java new file mode 100644 index 000000000..d05e328f9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineService.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 杂项出库单行 Service 接口 + */ +public interface MesWmMiscIssueLineService { + + /** + * 创建杂项出库单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMiscIssueLine(@Valid MesWmMiscIssueLineSaveReqVO createReqVO); + + /** + * 修改杂项出库单行 + * + * @param updateReqVO 修改信息 + */ + void updateMiscIssueLine(@Valid MesWmMiscIssueLineSaveReqVO updateReqVO); + + /** + * 删除杂项出库单行(级联删除明细) + * + * @param id 编号 + */ + void deleteMiscIssueLine(Long id); + + /** + * 获得杂项出库单行 + * + * @param id 编号 + * @return 杂项出库单行 + */ + MesWmMiscIssueLineDO getMiscIssueLine(Long id); + + /** + * 获得杂项出库单行分页 + * + * @param pageReqVO 分页参数 + * @return 杂项出库单行分页 + */ + PageResult getMiscIssueLinePage(MesWmMiscIssueLinePageReqVO pageReqVO); + + /** + * 按出库单编号获得行列表 + * + * @param issueId 出库单编号 + * @return 行列表 + */ + List getMiscIssueLineListByIssueId(Long issueId); + + /** + * 按出库单编号批量删除行 + * + * @param issueId 出库单编号 + */ + void deleteMiscIssueLineByIssueId(Long issueId); + + /** + * 校验杂项出库单行是否存在 + * + * @param id 编号 + */ + void validateMiscIssueLineExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java new file mode 100644 index 000000000..92936f9bf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.line.MesWmMiscIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue.MesWmMiscIssueLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MISC_ISSUE_LINE_NOT_EXISTS; + +/** + * MES 杂项出库单行 Service 实现类 + */ +@Service +@Validated +public class MesWmMiscIssueLineServiceImpl implements MesWmMiscIssueLineService { + + @Resource + private MesWmMiscIssueLineMapper miscIssueLineMapper; + + @Resource + @Lazy + private MesWmMiscIssueService miscIssueService; + + @Resource + @Lazy + private MesWmMiscIssueDetailService miscIssueDetailService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createMiscIssueLine(MesWmMiscIssueLineSaveReqVO createReqVO) { + // 1. 校验数据 + validateMiscIssueLineSaveData(createReqVO.getIssueId(), createReqVO); + + // 2. 新增行 + MesWmMiscIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmMiscIssueLineDO.class); + miscIssueLineMapper.insert(line); + + // 3.自动创建明细 + createReqVO.setId(line.getId()); + miscIssueDetailService.createMiscIssueDetail(createReqVO); + return line.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateMiscIssueLine(MesWmMiscIssueLineSaveReqVO updateReqVO) { + // 1.1 校验存在 + MesWmMiscIssueLineDO line = validateAndGetMiscIssueLine(updateReqVO.getId()); + // 1.2 校验数据 + validateMiscIssueLineSaveData(line.getIssueId(), updateReqVO); + + // 2. 更新行 + MesWmMiscIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscIssueLineDO.class); + miscIssueLineMapper.updateById(updateObj); + + // 3. 更新明细(基于行信息) + miscIssueDetailService.updateMiscIssueDetail(updateReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteMiscIssueLine(Long id) { + // 校验存在 + MesWmMiscIssueLineDO line = validateAndGetMiscIssueLine(id); + // 校验父单据存在且为可编辑状态 + miscIssueService.validateMiscIssueEditable(line.getIssueId()); + + // 删除行 + miscIssueLineMapper.deleteById(id); + // 删除明细 + miscIssueDetailService.deleteMiscIssueDetailByLineId(id); + } + + @Override + public MesWmMiscIssueLineDO getMiscIssueLine(Long id) { + return miscIssueLineMapper.selectById(id); + } + + @Override + public PageResult getMiscIssueLinePage(MesWmMiscIssueLinePageReqVO pageReqVO) { + return miscIssueLineMapper.selectPage(pageReqVO); + } + + @Override + public List getMiscIssueLineListByIssueId(Long issueId) { + return miscIssueLineMapper.selectListByIssueId(issueId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteMiscIssueLineByIssueId(Long issueId) { + // 删除明细 + miscIssueDetailService.deleteMiscIssueDetailByIssueId(issueId); + // 删除行 + miscIssueLineMapper.deleteByIssueId(issueId); + } + + @Override + public void validateMiscIssueLineExists(Long id) { + if (miscIssueLineMapper.selectById(id) == null) { + throw exception(WM_MISC_ISSUE_LINE_NOT_EXISTS); + } + } + + private MesWmMiscIssueLineDO validateAndGetMiscIssueLine(Long id) { + MesWmMiscIssueLineDO line = miscIssueLineMapper.selectById(id); + if (line == null) { + throw exception(WM_MISC_ISSUE_LINE_NOT_EXISTS); + } + return line; + } + + private void validateMiscIssueLineSaveData(Long issueId, MesWmMiscIssueLineSaveReqVO reqVO) { + // 校验父单据存在且为可编辑状态 + miscIssueService.validateMiscIssueEditable(issueId); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + // 校验仓库、库区、库位的父子关系 + warehouseAreaService.validateWarehouseAreaExists(reqVO.getWarehouseId(), + reqVO.getLocationId(), reqVO.getAreaId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueService.java new file mode 100644 index 000000000..36971d7c3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueService.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDO; +import jakarta.validation.Valid; + +/** + * MES 杂项出库单 Service 接口 + */ +public interface MesWmMiscIssueService { + + /** + * 创建杂项出库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMiscIssue(@Valid MesWmMiscIssueSaveReqVO createReqVO); + + /** + * 修改杂项出库单 + * + * @param updateReqVO 修改信息 + */ + void updateMiscIssue(@Valid MesWmMiscIssueSaveReqVO updateReqVO); + + /** + * 删除杂项出库单(级联删除行+明细) + * + * @param id 编号 + */ + void deleteMiscIssue(Long id); + + /** + * 获得杂项出库单 + * + * @param id 编号 + * @return 杂项出库单 + */ + MesWmMiscIssueDO getMiscIssue(Long id); + + /** + * 获得杂项出库单分页 + * + * @param pageReqVO 分页参数 + * @return 杂项出库单分页 + */ + PageResult getMiscIssuePage(MesWmMiscIssuePageReqVO pageReqVO); + + /** + * 提交杂项出库单(草稿 → 待执行出库) + * + * @param id 编号 + */ + void submitMiscIssue(Long id); + + /** + * 执行出库(待执行出库 → 已完成),扣减库存 + * + * @param id 编号 + */ + void finishMiscIssue(Long id); + + /** + * 取消杂项出库单(任意非已完成/已取消状态 → 已取消) + * + * @param id 编号 + */ + void cancelMiscIssue(Long id); + + /** + * 校验杂项出库单存在且处于可编辑状态(草稿) + * + * @param id 编号 + * @return 杂项出库单 + */ + MesWmMiscIssueDO validateMiscIssueEditable(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueServiceImpl.java new file mode 100644 index 000000000..749731bcb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueServiceImpl.java @@ -0,0 +1,193 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscissue; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo.MesWmMiscIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscissue.MesWmMiscIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscissue.MesWmMiscIssueMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscIssueStatusEnum; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 杂项出库单 Service 实现类 + */ +@Service +@Validated +@Slf4j +public class MesWmMiscIssueServiceImpl implements MesWmMiscIssueService { + + @Resource + private MesWmMiscIssueMapper miscIssueMapper; + + @Resource + private MesWmMiscIssueLineService miscIssueLineService; + @Resource + private MesWmTransactionService wmTransactionService; + + @Override + public Long createMiscIssue(MesWmMiscIssueSaveReqVO createReqVO) { + // 校验编码唯一 + validateCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesWmMiscIssueDO issue = BeanUtils.toBean(createReqVO, MesWmMiscIssueDO.class); + issue.setStatus(MesWmMiscIssueStatusEnum.PREPARE.getStatus()); + miscIssueMapper.insert(issue); + return issue.getId(); + } + + @Override + public void updateMiscIssue(MesWmMiscIssueSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateMiscIssueExistsAndDraft(updateReqVO.getId()); + // 校验编码唯一 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesWmMiscIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscIssueDO.class); + miscIssueMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteMiscIssue(Long id) { + // 校验存在 + 草稿状态 + validateMiscIssueExistsAndDraft(id); + + // 级联删除行 + miscIssueLineService.deleteMiscIssueLineByIssueId(id); + // 删除 + miscIssueMapper.deleteById(id); + } + + @Override + public MesWmMiscIssueDO getMiscIssue(Long id) { + return miscIssueMapper.selectById(id); + } + + @Override + public PageResult getMiscIssuePage(MesWmMiscIssuePageReqVO pageReqVO) { + return miscIssueMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitMiscIssue(Long id) { + // 校验存在 + 草稿状态 + validateMiscIssueExistsAndDraft(id); + // 校验至少有一条行 + List lines = miscIssueLineService.getMiscIssueLineListByIssueId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_MISC_ISSUE_NO_LINE); + } + + // 提交(草稿 → 待执行出库) + miscIssueMapper.updateById(new MesWmMiscIssueDO() + .setId(id).setStatus(MesWmMiscIssueStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishMiscIssue(Long id) { + // 1.1 校验存在 + MesWmMiscIssueDO issue = validateMiscIssueExists(id); + if (ObjUtil.notEqual(MesWmMiscIssueStatusEnum.APPROVED.getStatus(), issue.getStatus())) { + throw exception(WM_MISC_ISSUE_STATUS_INVALID); + } + // 1.2 校验至少有一条行 + List lines = miscIssueLineService.getMiscIssueLineListByIssueId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_MISC_ISSUE_NO_LINE); + } + + // 2. 遍历所有行,创建库存事务(扣减库存 + 记录流水) + createTransactionList(issue); + + // 3. 更新出库单状态(待执行出库 → 已完成) + miscIssueMapper.updateById(new MesWmMiscIssueDO() + .setId(id).setStatus(MesWmMiscIssueStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmMiscIssueDO issue) { + List lines = miscIssueLineService.getMiscIssueLineListByIssueId(issue.getId()); + wmTransactionService.createTransactionList(convertList(lines, line -> new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(line.getItemId()) + .setQuantity(line.getQuantity().negate()) // 出库数量为负数 + .setWarehouseId(line.getWarehouseId()).setLocationId(line.getLocationId()).setAreaId(line.getAreaId()) + .setBizType(MesBizTypeConstants.WM_MISC_ISSUE).setBizId(issue.getId()).setBizCode(issue.getCode()).setBizLineId(line.getId()))); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelMiscIssue(Long id) { + // 校验存在 + MesWmMiscIssueDO issue = validateMiscIssueExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(issue.getStatus(), + MesWmMiscIssueStatusEnum.FINISHED.getStatus(), + MesWmMiscIssueStatusEnum.CANCELED.getStatus())) { + throw exception(WM_MISC_ISSUE_CANCEL_NOT_ALLOWED); + } + // 取消 + miscIssueMapper.updateById(new MesWmMiscIssueDO() + .setId(id).setStatus(MesWmMiscIssueStatusEnum.CANCELED.getStatus())); + } + + @Override + public MesWmMiscIssueDO validateMiscIssueEditable(Long id) { + MesWmMiscIssueDO issue = validateMiscIssueExists(id); + if (ObjUtil.notEqual(issue.getStatus(), MesWmMiscIssueStatusEnum.PREPARE.getStatus())) { + throw exception(WM_MISC_ISSUE_STATUS_INVALID); + } + return issue; + } + + private MesWmMiscIssueDO validateMiscIssueExists(Long id) { + MesWmMiscIssueDO issue = miscIssueMapper.selectById(id); + if (issue == null) { + throw exception(WM_MISC_ISSUE_NOT_EXISTS); + } + return issue; + } + + /** + * 校验杂项出库单存在且为草稿状态 + */ + private MesWmMiscIssueDO validateMiscIssueExistsAndDraft(Long id) { + MesWmMiscIssueDO issue = validateMiscIssueExists(id); + if (ObjUtil.notEqual(MesWmMiscIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) { + throw exception(WM_MISC_ISSUE_STATUS_INVALID); + } + return issue; + } + + private void validateCodeUnique(Long id, String code) { + MesWmMiscIssueDO issue = miscIssueMapper.selectByCode(code); + if (issue == null) { + return; + } + if (ObjUtil.notEqual(id, issue.getId())) { + throw exception(WM_MISC_ISSUE_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailService.java new file mode 100644 index 000000000..0a44355a7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailService.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; + +/** + * MES 杂项入库明细 Service 接口 + */ +public interface MesWmMiscReceiptDetailService { + + /** + * 创建杂项入库明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO createReqVO); + + /** + * 更新杂项入库明细 + * + * @param updateReqVO 更新信息 + */ + void updateMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO updateReqVO); + + /** + * 删除杂项入库明细(根据入库单ID) + * + * @param receiptId 入库单ID + */ + void deleteMiscReceiptDetailByReceiptId(Long receiptId); + + /** + * 删除杂项入库明细(根据行ID) + * + * @param lineId 行ID + */ + void deleteMiscReceiptDetailByLineId(Long lineId); + + /** + * 校验杂项入库明细是否存在 + * + * @param id 编号 + */ + void validateMiscReceiptDetailExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailServiceImpl.java new file mode 100644 index 000000000..9676ec016 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptDetailServiceImpl.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt.MesWmMiscReceiptDetailMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MISC_RECEIPT_DETAIL_NOT_EXISTS; + +/** + * MES 杂项入库明细 Service 实现类 + */ +@Service +@Validated +public class MesWmMiscReceiptDetailServiceImpl implements MesWmMiscReceiptDetailService { + + @Resource + private MesWmMiscReceiptDetailMapper receiptDetailMapper; + + @Override + public Long createMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO createReqVO) { + MesWmMiscReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmMiscReceiptDetailDO.class); + detail.setId(null); // 清空 id,让数据库自动生成 + detail.setLineId(createReqVO.getId()); // VO 的 id 就是 lineId + receiptDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateMiscReceiptDetail(MesWmMiscReceiptLineSaveReqVO updateReqVO) { + // 基于 lineId 查询唯一的 detail 记录(VO 的 id 字段是 lineId) + List details = receiptDetailMapper.selectListByLineId(updateReqVO.getId()); + if (CollUtil.isEmpty(details)) { + return; + } + + // 更新 detail(应该只有一条记录) + MesWmMiscReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscReceiptDetailDO.class); + updateObj.setId(details.get(0).getId()); // 使用查询到的 detail id + updateObj.setLineId(updateReqVO.getId()); // VO 的 id 就是 lineId + receiptDetailMapper.updateById(updateObj); + } + + @Override + public void deleteMiscReceiptDetailByReceiptId(Long receiptId) { + receiptDetailMapper.deleteByReceiptId(receiptId); + } + + @Override + public void deleteMiscReceiptDetailByLineId(Long lineId) { + receiptDetailMapper.deleteByLineId(lineId); + } + + @Override + public void validateMiscReceiptDetailExists(Long id) { + if (receiptDetailMapper.selectById(id) == null) { + throw exception(WM_MISC_RECEIPT_DETAIL_NOT_EXISTS); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineService.java new file mode 100644 index 000000000..9d3b8178a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineService.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 杂项入库单行 Service 接口 + */ +public interface MesWmMiscReceiptLineService { + + /** + * 创建杂项入库单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMiscReceiptLine(@Valid MesWmMiscReceiptLineSaveReqVO createReqVO); + + /** + * 修改杂项入库单行 + * + * @param updateReqVO 修改信息 + */ + void updateMiscReceiptLine(@Valid MesWmMiscReceiptLineSaveReqVO updateReqVO); + + /** + * 删除杂项入库单行 + * + * @param id 编号 + */ + void deleteMiscReceiptLine(Long id); + + /** + * 获得杂项入库单行 + * + * @param id 编号 + * @return 杂项入库单行 + */ + MesWmMiscReceiptLineDO getMiscReceiptLine(Long id); + + /** + * 获得杂项入库单行列表 + * + * @param receiptId 入库单编号 + * @return 杂项入库单行列表 + */ + List getMiscReceiptLineListByReceiptId(Long receiptId); + + /** + * 获得杂项入库单行分页 + * + * @param pageReqVO 分页参数 + * @return 杂项入库单行分页 + */ + PageResult getMiscReceiptLinePage(MesWmMiscReceiptLinePageReqVO pageReqVO); + + /** + * 删除指定入库单的所有行(级联删除) + * + * @param receiptId 入库单编号 + */ + void deleteByReceiptId(Long receiptId); + + /** + * 校验杂项入库单行存在 + * + * @param id 编号 + * @return 杂项入库单行 + */ + MesWmMiscReceiptLineDO validateMiscReceiptLineExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java new file mode 100644 index 000000000..a659f5856 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.line.MesWmMiscReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt.MesWmMiscReceiptLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MISC_RECEIPT_LINE_NOT_EXISTS; + +/** + * MES 杂项入库单行 Service 实现类 + */ +@Service +@Validated +public class MesWmMiscReceiptLineServiceImpl implements MesWmMiscReceiptLineService { + + @Resource + private MesWmMiscReceiptLineMapper miscReceiptLineMapper; + + @Resource + @Lazy + private MesWmMiscReceiptService miscReceiptService; + @Resource + @Lazy + private MesWmMiscReceiptDetailService miscReceiptDetailService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createMiscReceiptLine(MesWmMiscReceiptLineSaveReqVO createReqVO) { + // 1. 校验 + validateLineSaveData(createReqVO); + + // 2. 新增行 + MesWmMiscReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmMiscReceiptLineDO.class); + miscReceiptLineMapper.insert(line); + + // 3. 自动创建明细 + createReqVO.setId(line.getId()); + miscReceiptDetailService.createMiscReceiptDetail(createReqVO); + return line.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateMiscReceiptLine(MesWmMiscReceiptLineSaveReqVO updateReqVO) { + // 1. 校验 + MesWmMiscReceiptLineDO line = validateMiscReceiptLineExists(updateReqVO.getId()); + updateReqVO.setReceiptId(line.getReceiptId()); + + // 2. 更新行 + MesWmMiscReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscReceiptLineDO.class); + miscReceiptLineMapper.updateById(updateObj); + + // 3. 更新明细(基于行信息) + miscReceiptDetailService.updateMiscReceiptDetail(updateReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteMiscReceiptLine(Long id) { + // 校验存在 + MesWmMiscReceiptLineDO line = validateMiscReceiptLineExists(id); + // 校验父单据存在且为可编辑状态 + miscReceiptService.validateMiscReceiptEditable(line.getReceiptId()); + + // 删除行 + miscReceiptLineMapper.deleteById(id); + // 删除明细 + miscReceiptDetailService.deleteMiscReceiptDetailByLineId(id); + } + + @Override + public MesWmMiscReceiptLineDO getMiscReceiptLine(Long id) { + return miscReceiptLineMapper.selectById(id); + } + + @Override + public List getMiscReceiptLineListByReceiptId(Long receiptId) { + return miscReceiptLineMapper.selectListByReceiptId(receiptId); + } + + @Override + public PageResult getMiscReceiptLinePage(MesWmMiscReceiptLinePageReqVO pageReqVO) { + return miscReceiptLineMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteByReceiptId(Long receiptId) { + // 先删除明细 + miscReceiptDetailService.deleteMiscReceiptDetailByReceiptId(receiptId); + // 再删除行 + miscReceiptLineMapper.deleteByReceiptId(receiptId); + } + + @Override + public MesWmMiscReceiptLineDO validateMiscReceiptLineExists(Long id) { + MesWmMiscReceiptLineDO line = miscReceiptLineMapper.selectById(id); + if (line == null) { + throw exception(WM_MISC_RECEIPT_LINE_NOT_EXISTS); + } + return line; + } + + /** + * 校验行保存数据(物料存在、仓库层级关系) + */ + private void validateLineSaveData(MesWmMiscReceiptLineSaveReqVO reqVO) { + // 校验父单据存在且为可编辑状态 + miscReceiptService.validateMiscReceiptEditable(reqVO.getReceiptId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + // 校验仓库层级关系(仓库 - 库位 - 库区) + warehouseAreaService.validateWarehouseAreaExists(reqVO.getWarehouseId(), + reqVO.getLocationId(), reqVO.getAreaId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptService.java new file mode 100644 index 000000000..08e607f96 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptService.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.MesWmMiscReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.MesWmMiscReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDO; +import jakarta.validation.Valid; + +/** + * MES 杂项入库单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmMiscReceiptService { + + /** + * 创建杂项入库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMiscReceipt(@Valid MesWmMiscReceiptSaveReqVO createReqVO); + + /** + * 修改杂项入库单 + * + * @param updateReqVO 修改信息 + */ + void updateMiscReceipt(@Valid MesWmMiscReceiptSaveReqVO updateReqVO); + + /** + * 删除杂项入库单(级联删除行) + * + * @param id 编号 + */ + void deleteMiscReceipt(Long id); + + /** + * 获得杂项入库单 + * + * @param id 编号 + * @return 杂项入库单 + */ + MesWmMiscReceiptDO getMiscReceipt(Long id); + + /** + * 获得杂项入库单分页 + * + * @param pageReqVO 分页参数 + * @return 杂项入库单分页 + */ + PageResult getMiscReceiptPage(MesWmMiscReceiptPageReqVO pageReqVO); + + /** + * 提交审批(草稿 → 已审批) + * + * @param id 编号 + */ + void submitMiscReceipt(Long id); + + /** + * 执行入库(已审批 → 已完成),更新库存台账 + * + * @param id 编号 + */ + void finishMiscReceipt(Long id); + + /** + * 取消杂项入库单(草稿/已审批 → 已取消) + * + * @param id 编号 + */ + void cancelMiscReceipt(Long id); + + /** + * 校验杂项入库单存在 + * + * @param id 编号 + * @return 杂项入库单 + */ + MesWmMiscReceiptDO validateMiscReceiptExists(Long id); + + /** + * 校验杂项入库单是否可编辑(存在且为草稿状态) + * + * @param id 编号 + */ + void validateMiscReceiptEditable(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptServiceImpl.java new file mode 100644 index 000000000..72a9f3d0a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptServiceImpl.java @@ -0,0 +1,188 @@ +package cn.iocoder.yudao.module.mes.service.wm.miscreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.MesWmMiscReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo.MesWmMiscReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt.MesWmMiscReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.miscreceipt.MesWmMiscReceiptMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscReceiptStatusEnum; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 杂项入库单 Service 实现类 + */ +@Service +@Validated +@Slf4j +public class MesWmMiscReceiptServiceImpl implements MesWmMiscReceiptService { + + @Resource + private MesWmMiscReceiptMapper miscReceiptMapper; + + @Resource + @Lazy + private MesWmMiscReceiptLineService miscReceiptLineService; + @Resource + private MesWmTransactionService wmTransactionService; + + @Override + public Long createMiscReceipt(MesWmMiscReceiptSaveReqVO createReqVO) { + // 校验编码唯一 + validateCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesWmMiscReceiptDO receipt = BeanUtils.toBean(createReqVO, MesWmMiscReceiptDO.class); + receipt.setStatus(MesWmMiscReceiptStatusEnum.PREPARE.getStatus()); + miscReceiptMapper.insert(receipt); + return receipt.getId(); + } + + @Override + public void updateMiscReceipt(MesWmMiscReceiptSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateMiscReceiptExistsAndPrepare(updateReqVO.getId()); + // 校验编码唯一 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesWmMiscReceiptDO updateObj = BeanUtils.toBean(updateReqVO, MesWmMiscReceiptDO.class); + miscReceiptMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteMiscReceipt(Long id) { + // 校验存在 + 草稿状态 + validateMiscReceiptExistsAndPrepare(id); + + // 级联删除行和明细 + miscReceiptLineService.deleteByReceiptId(id); + // 删除主表 + miscReceiptMapper.deleteById(id); + } + + @Override + public MesWmMiscReceiptDO getMiscReceipt(Long id) { + return miscReceiptMapper.selectById(id); + } + + @Override + public PageResult getMiscReceiptPage(MesWmMiscReceiptPageReqVO pageReqVO) { + return miscReceiptMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitMiscReceipt(Long id) { + // 校验存在 + 草稿状态 + validateMiscReceiptExistsAndPrepare(id); + // 校验至少有一条行 + List lines = miscReceiptLineService.getMiscReceiptLineListByReceiptId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_MISC_RECEIPT_NO_LINE); + } + + // 提交审批(草稿 → 已审批) + miscReceiptMapper.updateById(new MesWmMiscReceiptDO() + .setId(id).setStatus(MesWmMiscReceiptStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishMiscReceipt(Long id) { + // 校验存在 + MesWmMiscReceiptDO receipt = validateMiscReceiptExists(id); + if (ObjUtil.notEqual(MesWmMiscReceiptStatusEnum.APPROVED.getStatus(), receipt.getStatus())) { + throw exception(WM_MISC_RECEIPT_STATUS_NOT_APPROVED); + } + + // 2. 遍历所有行,创建库存事务(增加库存 + 记录流水) + createTransactionList(receipt); + + // 3. 执行入库(已审批 → 已完成) + miscReceiptMapper.updateById(new MesWmMiscReceiptDO() + .setId(id).setStatus(MesWmMiscReceiptStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmMiscReceiptDO receipt) { + List lines = miscReceiptLineService.getMiscReceiptLineListByReceiptId(receipt.getId()); + wmTransactionService.createTransactionList(convertList(lines, line -> new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(line.getItemId()) + .setQuantity(line.getQuantity()) // 入库数量为正数 + .setWarehouseId(line.getWarehouseId()).setLocationId(line.getLocationId()).setAreaId(line.getAreaId()) + .setBizType(MesBizTypeConstants.WM_MISC_RECPT).setBizId(receipt.getId()).setBizCode(receipt.getCode()).setBizLineId(line.getId()))); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelMiscReceipt(Long id) { + // 校验存在 + MesWmMiscReceiptDO receipt = validateMiscReceiptExists(id); + + // 已完成和已取消状态不允许取消 + if (ObjUtil.equal(MesWmMiscReceiptStatusEnum.FINISHED.getStatus(), receipt.getStatus()) + || ObjUtil.equal(MesWmMiscReceiptStatusEnum.CANCELED.getStatus(), receipt.getStatus())) { + throw exception(WM_MISC_RECEIPT_CANCEL_NOT_ALLOWED); + } + + // 取消 + miscReceiptMapper.updateById(new MesWmMiscReceiptDO() + .setId(id).setStatus(MesWmMiscReceiptStatusEnum.CANCELED.getStatus())); + } + + @Override + public MesWmMiscReceiptDO validateMiscReceiptExists(Long id) { + MesWmMiscReceiptDO receipt = miscReceiptMapper.selectById(id); + if (receipt == null) { + throw exception(WM_MISC_RECEIPT_NOT_EXISTS); + } + return receipt; + } + + private void validateCodeUnique(Long id, String code) { + MesWmMiscReceiptDO receipt = miscReceiptMapper.selectByCode(code); + if (receipt == null) { + return; + } + if (id == null || ObjUtil.notEqual(id, receipt.getId())) { + throw exception(WM_MISC_RECEIPT_CODE_DUPLICATE); + } + } + + private MesWmMiscReceiptDO validateMiscReceiptExistsAndPrepare(Long id) { + MesWmMiscReceiptDO receipt = validateMiscReceiptExists(id); + if (ObjUtil.notEqual(MesWmMiscReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())) { + throw exception(WM_MISC_RECEIPT_STATUS_NOT_PREPARE); + } + return receipt; + } + + /** + * 校验入库单是否可编辑(存在且为草稿状态) + * + * @param id 入库单ID + */ + public void validateMiscReceiptEditable(Long id) { + validateMiscReceiptExistsAndPrepare(id); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailService.java new file mode 100644 index 000000000..e7ae9cd97 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailService.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 外协发料单明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmOutsourceIssueDetailService { + + /** + * 创建外协发料单明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceIssueDetail(@Valid MesWmOutsourceIssueDetailSaveReqVO createReqVO); + + /** + * 修改外协发料单明细 + * + * @param updateReqVO 修改信息 + */ + void updateOutsourceIssueDetail(@Valid MesWmOutsourceIssueDetailSaveReqVO updateReqVO); + + /** + * 删除外协发料单明细 + * + * @param id 编号 + */ + void deleteOutsourceIssueDetail(Long id); + + /** + * 获得外协发料单明细 + * + * @param id 编号 + * @return 外协发料单明细 + */ + MesWmOutsourceIssueDetailDO getOutsourceIssueDetail(Long id); + + /** + * 获得外协发料单明细列表 + * + * @param issueId 发料单ID + * @return 外协发料单明细列表 + */ + List getOutsourceIssueDetailListByIssueId(Long issueId); + + /** + * 获得外协发料单明细列表 + * + * @param lineId 行ID + * @return 外协发料单明细列表 + */ + List getOutsourceIssueDetailListByLineId(Long lineId); + + /** + * 删除外协发料单明细 + * + * @param issueId 发料单ID + */ + void deleteOutsourceIssueDetailByIssueId(Long issueId); + + /** + * 删除外协发料单明细 + * + * @param lineId 行ID + */ + void deleteOutsourceIssueDetailByLineId(Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java new file mode 100644 index 000000000..8ad07979b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueDetailMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS; + +/** + * MES 外协发料单明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssueDetailService { + + @Resource + private MesWmOutsourceIssueDetailMapper outsourceIssueDetailMapper; + @Resource + @Lazy + private MesWmOutsourceIssueService outsourceIssueService; + @Resource + private MesMdItemService itemService; + + @Override + public Long createOutsourceIssueDetail(MesWmOutsourceIssueDetailSaveReqVO createReqVO) { + // 校验数据 + validateOutsourceIssueDetailSaveData(createReqVO); + + // 插入 + MesWmOutsourceIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueDetailDO.class); + outsourceIssueDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateOutsourceIssueDetail(MesWmOutsourceIssueDetailSaveReqVO updateReqVO) { + // 校验存在 + validateOutsourceIssueDetailExists(updateReqVO.getId()); + // 校验数据 + validateOutsourceIssueDetailSaveData(updateReqVO); + + // 更新 + MesWmOutsourceIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueDetailDO.class); + outsourceIssueDetailMapper.updateById(updateObj); + } + + @Override + public void deleteOutsourceIssueDetail(Long id) { + // 校验存在 + validateOutsourceIssueDetailExists(id); + // 删除 + outsourceIssueDetailMapper.deleteById(id); + } + + @Override + public MesWmOutsourceIssueDetailDO getOutsourceIssueDetail(Long id) { + return outsourceIssueDetailMapper.selectById(id); + } + + @Override + public List getOutsourceIssueDetailListByIssueId(Long issueId) { + return outsourceIssueDetailMapper.selectListByIssueId(issueId); + } + + @Override + public List getOutsourceIssueDetailListByLineId(Long lineId) { + return outsourceIssueDetailMapper.selectListByLineId(lineId); + } + + @Override + public void deleteOutsourceIssueDetailByIssueId(Long issueId) { + outsourceIssueDetailMapper.deleteByIssueId(issueId); + } + + @Override + public void deleteOutsourceIssueDetailByLineId(Long lineId) { + outsourceIssueDetailMapper.deleteByLineId(lineId); + } + + private void validateOutsourceIssueDetailExists(Long id) { + if (outsourceIssueDetailMapper.selectById(id) == null) { + throw exception(WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS); + } + } + + private void validateOutsourceIssueDetailSaveData(MesWmOutsourceIssueDetailSaveReqVO saveReqVO) { + // 校验关联的发料单存在 + outsourceIssueService.getOutsourceIssue(saveReqVO.getIssueId()); + // 校验关联的物料存在 + itemService.validateItemExists(saveReqVO.getItemId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineService.java new file mode 100644 index 000000000..ea2f03fbb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineService.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 外协发料单行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmOutsourceIssueLineService { + + /** + * 创建外协发料单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceIssueLine(@Valid MesWmOutsourceIssueLineSaveReqVO createReqVO); + + /** + * 修改外协发料单行 + * + * @param updateReqVO 修改信息 + */ + void updateOutsourceIssueLine(@Valid MesWmOutsourceIssueLineSaveReqVO updateReqVO); + + /** + * 删除外协发料单行 + * + * @param id 编号 + */ + void deleteOutsourceIssueLine(Long id); + + /** + * 获得外协发料单行 + * + * @param id 编号 + * @return 外协发料单行 + */ + MesWmOutsourceIssueLineDO getOutsourceIssueLine(Long id); + + /** + * 获得外协发料单行分页 + * + * @param pageReqVO 分页参数 + * @return 外协发料单行分页 + */ + PageResult getOutsourceIssueLinePage(MesWmOutsourceIssueLinePageReqVO pageReqVO); + + /** + * 获得外协发料单行列表 + * + * @param issueId 发料单ID + * @return 外协发料单行列表 + */ + List getOutsourceIssueLineListByIssueId(Long issueId); + + /** + * 删除外协发料单行 + * + * @param issueId 发料单ID + */ + void deleteOutsourceIssueLineByIssueId(Long issueId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java new file mode 100644 index 000000000..a556cd5b1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java @@ -0,0 +1,158 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.line.MesWmOutsourceIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueLineMapper; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderBomService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_LINE_ITEM_NOT_IN_BOM; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_NOT_EXISTS; + +/** + * MES 外协发料单行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmOutsourceIssueLineServiceImpl implements MesWmOutsourceIssueLineService { + + @Resource + private MesWmOutsourceIssueLineMapper outsourceIssueLineMapper; + + @Resource + private MesWmOutsourceIssueDetailService outsourceIssueDetailService; + @Resource + @Lazy + private MesWmOutsourceIssueService outsourceIssueService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmBatchService batchService; + @Resource + private MesProWorkOrderBomService workOrderBomService; + + @Override + public Long createOutsourceIssueLine(MesWmOutsourceIssueLineSaveReqVO createReqVO) { + // 校验数据 + validateOutsourceIssueLineSaveData(createReqVO); + // 根据 batchCode 解析 batchId + fillBatchId(createReqVO); + + // 插入 + MesWmOutsourceIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueLineDO.class); + outsourceIssueLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateOutsourceIssueLine(MesWmOutsourceIssueLineSaveReqVO updateReqVO) { + // 校验存在 + validateOutsourceIssueLineExists(updateReqVO.getId()); + // 校验数据 + validateOutsourceIssueLineSaveData(updateReqVO); + // 根据 batchCode 解析 batchId + fillBatchId(updateReqVO); + + // 更新 + MesWmOutsourceIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueLineDO.class); + outsourceIssueLineMapper.updateById(updateObj); + } + + @Override + public void deleteOutsourceIssueLine(Long id) { + // 校验存在 + validateOutsourceIssueLineExists(id); + + // 级联删除明细 + outsourceIssueDetailService.deleteOutsourceIssueDetailByLineId(id); + // 删除行 + outsourceIssueLineMapper.deleteById(id); + } + + @Override + public MesWmOutsourceIssueLineDO getOutsourceIssueLine(Long id) { + return outsourceIssueLineMapper.selectById(id); + } + + @Override + public PageResult getOutsourceIssueLinePage(MesWmOutsourceIssueLinePageReqVO pageReqVO) { + return outsourceIssueLineMapper.selectPage(pageReqVO); + } + + @Override + public List getOutsourceIssueLineListByIssueId(Long issueId) { + return outsourceIssueLineMapper.selectListByIssueId(issueId); + } + + @Override + public void deleteOutsourceIssueLineByIssueId(Long issueId) { + outsourceIssueLineMapper.deleteByIssueId(issueId); + } + + private void validateOutsourceIssueLineExists(Long id) { + if (outsourceIssueLineMapper.selectById(id) == null) { + throw exception(WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS); + } + } + + private void validateOutsourceIssueLineSaveData(MesWmOutsourceIssueLineSaveReqVO saveReqVO) { + // 校验关联的发料单存在 + MesWmOutsourceIssueDO issue = outsourceIssueService.getOutsourceIssue(saveReqVO.getIssueId()); + if (issue == null) { + throw exception(WM_OUTSOURCE_ISSUE_NOT_EXISTS); + } + // 校验关联的物料存在 + itemService.validateItemExists(saveReqVO.getItemId()); + // 校验物料是否在工单 BOM 中 + validateItemInWorkOrderBom(issue.getWorkOrderId(), saveReqVO.getItemId()); + } + + private void validateItemInWorkOrderBom(Long workOrderId, Long itemId) { + if (workOrderId == null) { + return; + } + // 获取当前外协工单的 BOM 列表 + List workOrderBoms = workOrderBomService.getWorkOrderBomListByWorkOrderId(workOrderId); + if (CollUtil.isEmpty(workOrderBoms)) { + return; + } + // 检查发料的物料是否在 BOM 列表中 + MesProWorkOrderBomDO workOrderBom = CollUtil.findOne(workOrderBoms, + bom -> bom.getItemId().equals(itemId)); + if (workOrderBom == null) { + throw exception(WM_OUTSOURCE_ISSUE_LINE_ITEM_NOT_IN_BOM); + } + } + + /** + * 根据 batchCode 解析 batchId + */ + private void fillBatchId(MesWmOutsourceIssueLineSaveReqVO reqVO) { + if (StrUtil.isBlank(reqVO.getBatchCode())) { + reqVO.setBatchId(null); + return; + } + MesWmBatchDO batch = batchService.getBatchByCode(reqVO.getBatchCode()); + reqVO.setBatchId(batch != null ? batch.getId() : null); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java new file mode 100644 index 000000000..042bad18c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO; +import jakarta.validation.Valid; + +/** + * MES 外协发料单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmOutsourceIssueService { + + /** + * 创建外协发料单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceIssue(@Valid MesWmOutsourceIssueSaveReqVO createReqVO); + + /** + * 修改外协发料单 + * + * @param updateReqVO 修改信息 + */ + void updateOutsourceIssue(@Valid MesWmOutsourceIssueSaveReqVO updateReqVO); + + /** + * 删除外协发料单(级联删除行和明细) + * + * @param id 编号 + */ + void deleteOutsourceIssue(Long id); + + /** + * 获得外协发料单 + * + * @param id 编号 + * @return 外协发料单 + */ + MesWmOutsourceIssueDO getOutsourceIssue(Long id); + + /** + * 获得外协发料单分页 + * + * @param pageReqVO 分页参数 + * @return 外协发料单分页 + */ + PageResult getOutsourceIssuePage(MesWmOutsourceIssuePageReqVO pageReqVO); + + /** + * 提交到待拣货(草稿 → 待拣货) + * + * @param id 编号 + */ + void submitOutsourceIssue(Long id); + + /** + * 执行拣货(待拣货 → 待执行出库) + * + * @param id 编号 + */ + void stockOutsourceIssue(Long id); + + /** + * 完成外协发料出库(待执行出库 → 已完成,扣减库存) + * + * @param id 编号 + */ + void finishOutsourceIssue(Long id); + + /** + * 取消外协发料单 + * + * @param id 编号 + */ + void cancelOutsourceIssue(Long id); + + /** + * 校验外协发料单数量(行数量 = 明细数量之和) + * + * @param id 编号 + * @return true 表示数量匹配,false 表示不匹配 + */ + Boolean checkOutsourceIssueQuantity(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java new file mode 100644 index 000000000..3193f3cb2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java @@ -0,0 +1,282 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.MesWmOutsourceIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueMapper; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; +import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderTypeEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceIssueStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 外协发料单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmOutsourceIssueServiceImpl implements MesWmOutsourceIssueService { + + @Resource + private MesWmOutsourceIssueMapper outsourceIssueMapper; + + @Resource + private MesWmOutsourceIssueLineService outsourceIssueLineService; + @Resource + private MesWmOutsourceIssueDetailService outsourceIssueDetailService; + @Resource + private MesMdVendorService vendorService; + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesWmTransactionService wmTransactionService; + @Resource + private MesMdAutoCodeRecordService autoCodeRecordService; + + @Override + public Long createOutsourceIssue(MesWmOutsourceIssueSaveReqVO createReqVO) { + // 自动生成编码 + if (StrUtil.isEmpty(createReqVO.getCode())) { + createReqVO.setCode(autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.WM_OUTSOURCE_ISSUE_CODE.getCode())); + } + // 校验数据 + validateOutsourceIssueSaveData(createReqVO); + + // 插入 + MesWmOutsourceIssueDO issue = BeanUtils.toBean(createReqVO, MesWmOutsourceIssueDO.class); + issue.setStatus(MesWmOutsourceIssueStatusEnum.PREPARE.getStatus()); + outsourceIssueMapper.insert(issue); + return issue.getId(); + } + + @Override + public void updateOutsourceIssue(MesWmOutsourceIssueSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateOutsourceIssueExistsAndDraft(updateReqVO.getId()); + // 校验数据 + validateOutsourceIssueSaveData(updateReqVO); + + // 更新 + MesWmOutsourceIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceIssueDO.class); + outsourceIssueMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteOutsourceIssue(Long id) { + // 校验存在 + 草稿状态 + validateOutsourceIssueExistsAndDraft(id); + + // 级联删除行和明细 + outsourceIssueLineService.deleteOutsourceIssueLineByIssueId(id); + outsourceIssueDetailService.deleteOutsourceIssueDetailByIssueId(id); + // 删除主表 + outsourceIssueMapper.deleteById(id); + } + + @Override + public MesWmOutsourceIssueDO getOutsourceIssue(Long id) { + return outsourceIssueMapper.selectById(id); + } + + @Override + public PageResult getOutsourceIssuePage(MesWmOutsourceIssuePageReqVO pageReqVO) { + return outsourceIssueMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitOutsourceIssue(Long id) { + // 1.1 校验存在 + 草稿状态 + validateOutsourceIssueExistsAndDraft(id); + // 1.2 检查是否有发料行 + List lines = outsourceIssueLineService.getOutsourceIssueLineListByIssueId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_OUTSOURCE_ISSUE_NO_LINE); + } + + // 2. 更新单据状态为待拣货 + outsourceIssueMapper.updateById(new MesWmOutsourceIssueDO() + .setId(id).setStatus(MesWmOutsourceIssueStatusEnum.APPROVING.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockOutsourceIssue(Long id) { + // 1.1 校验存在 + 待拣货状态 + MesWmOutsourceIssueDO issue = validateOutsourceIssueExists(id); + if (ObjUtil.notEqual(MesWmOutsourceIssueStatusEnum.APPROVING.getStatus(), issue.getStatus())) { + throw exception(WM_OUTSOURCE_ISSUE_STATUS_NOT_APPROVING); + } + // 1.2 校验数量一致性(行数量 = 明细数量之和) + List lines = outsourceIssueLineService.getOutsourceIssueLineListByIssueId(id); + if (CollUtil.isNotEmpty(lines)) { + // 批量查询所有明细 + List allDetails = outsourceIssueDetailService.getOutsourceIssueDetailListByIssueId(id); + Map> detailMap = CollectionUtils.convertMultiMap( + allDetails, MesWmOutsourceIssueDetailDO::getLineId); + // 检查每行的明细数量 + for (MesWmOutsourceIssueLineDO line : lines) { + List details = detailMap.getOrDefault(line.getId(), List.of()); + BigDecimal totalDetailQuantity = CollectionUtils.getSumValue(details, + MesWmOutsourceIssueDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + // 对比行数量与明细总数量,不满足直接抛出 + if (line.getQuantity().compareTo(totalDetailQuantity) != 0) { + throw exception(WM_OUTSOURCE_ISSUE_QUANTITY_MISMATCH); + } + } + } + + // 2. 更新单据状态为待执行出库 + outsourceIssueMapper.updateById(new MesWmOutsourceIssueDO() + .setId(id).setStatus(MesWmOutsourceIssueStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishOutsourceIssue(Long id) { + // 1. 校验存在 + 待执行出库状态 + MesWmOutsourceIssueDO issue = validateOutsourceIssueExists(id); + if (ObjUtil.notEqual(MesWmOutsourceIssueStatusEnum.APPROVED.getStatus(), issue.getStatus())) { + throw exception(WM_OUTSOURCE_ISSUE_STATUS_NOT_APPROVED); + } + + // 2. 遍历所有明细,创建库存事务(扣减库存 + 记录流水) + createTransactionList(issue); + + // 3. 更新单据状态为已完成 + outsourceIssueMapper.updateById(new MesWmOutsourceIssueDO() + .setId(id).setStatus(MesWmOutsourceIssueStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmOutsourceIssueDO issue) { + List details = outsourceIssueDetailService.getOutsourceIssueDetailListByIssueId(issue.getId()); + wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity().negate()) // 出库数量为负数 + .setBatchId(detail.getBatchId()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setVendorId(issue.getVendorId()) + .setBizType(MesBizTypeConstants.WM_OUTSOURCE_ISSUE).setBizId(issue.getId()) + .setBizCode(issue.getCode()).setBizLineId(detail.getLineId()))); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelOutsourceIssue(Long id) { + // 校验存在 + MesWmOutsourceIssueDO issue = validateOutsourceIssueExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(issue.getStatus(), + MesWmOutsourceIssueStatusEnum.FINISHED.getStatus(), + MesWmOutsourceIssueStatusEnum.CANCELLED.getStatus())) { + throw exception(WM_OUTSOURCE_ISSUE_CANCEL_NOT_ALLOWED); + } + + // 取消 + outsourceIssueMapper.updateById(new MesWmOutsourceIssueDO() + .setId(id).setStatus(MesWmOutsourceIssueStatusEnum.CANCELLED.getStatus())); + } + + @Override + public Boolean checkOutsourceIssueQuantity(Long id) { + List lines = outsourceIssueLineService.getOutsourceIssueLineListByIssueId(id); + if (CollUtil.isEmpty(lines)) { + return true; + } + // 批量查询所有明细 + List allDetails = outsourceIssueDetailService.getOutsourceIssueDetailListByIssueId(id); + Map> detailMap = CollectionUtils.convertMultiMap( + allDetails, MesWmOutsourceIssueDetailDO::getLineId); + // 检查每行的明细数量 + for (MesWmOutsourceIssueLineDO line : lines) { + List details = detailMap.getOrDefault(line.getId(), List.of()); + BigDecimal totalDetailQuantity = CollectionUtils.getSumValue(details, + MesWmOutsourceIssueDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + // 对比行数量与明细总数量 + if (line.getQuantity().compareTo(totalDetailQuantity) != 0) { + return false; + } + } + return true; + } + + /** + * 校验外协发料单存在 + */ + private MesWmOutsourceIssueDO validateOutsourceIssueExists(Long id) { + MesWmOutsourceIssueDO issue = outsourceIssueMapper.selectById(id); + if (issue == null) { + throw exception(WM_OUTSOURCE_ISSUE_NOT_EXISTS); + } + return issue; + } + + /** + * 校验外协发料单存在且为草稿状态 + */ + private MesWmOutsourceIssueDO validateOutsourceIssueExistsAndDraft(Long id) { + MesWmOutsourceIssueDO issue = validateOutsourceIssueExists(id); + if (ObjUtil.notEqual(MesWmOutsourceIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) { + throw exception(WM_OUTSOURCE_ISSUE_STATUS_NOT_PREPARE); + } + return issue; + } + + private void validateOutsourceIssueSaveData(MesWmOutsourceIssueSaveReqVO saveReqVO) { + // 校验编码唯一 + validateCodeUnique(saveReqVO.getId(), saveReqVO.getCode()); + // 校验供应商存在 + if (saveReqVO.getVendorId() != null) { + vendorService.validateVendorExists(saveReqVO.getVendorId()); + } + // 校验工单存在且类型为外协(代工) + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(saveReqVO.getWorkOrderId()); + if (ObjUtil.notEqual(workOrder.getType(), MesProWorkOrderTypeEnum.OUTSOURCE.getType())) { + throw exception(WM_OUTSOURCE_ISSUE_WORK_ORDER_TYPE_INVALID); + } + } + + /** + * 校验编码唯一性 + */ + private void validateCodeUnique(Long id, String code) { + MesWmOutsourceIssueDO issue = outsourceIssueMapper.selectByCode(code); + if (issue == null) { + return; + } + if (ObjUtil.notEqual(id, issue.getId())) { + throw exception(WM_OUTSOURCE_ISSUE_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailService.java new file mode 100644 index 000000000..10e0b5123 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailService.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.detail.MesWmOutsourceReceiptDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDetailDO; + +import java.util.List; + +/** + * MES 委外收货明细 Service 接口 + */ +public interface MesWmOutsourceReceiptDetailService { + + /** + * 创建外协入库明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceReceiptDetail(MesWmOutsourceReceiptDetailSaveReqVO createReqVO); + + /** + * 更新外协入库明细 + * + * @param updateReqVO 更新信息 + */ + void updateOutsourceReceiptDetail(MesWmOutsourceReceiptDetailSaveReqVO updateReqVO); + + /** + * 删除外协入库明细 + * + * @param id 编号 + */ + void deleteOutsourceReceiptDetail(Long id); + + /** + * 获得外协入库明细 + * + * @param id 编号 + * @return 外协入库明细 + */ + MesWmOutsourceReceiptDetailDO getOutsourceReceiptDetail(Long id); + + /** + * 获得委外收货明细列表(根据收货单编号) + * + * @param receiptId 收货单编号 + * @return 委外收货明细列表 + */ + List getOutsourceReceiptDetailListByReceiptId(Long receiptId); + + /** + * 获得委外收货明细列表(根据行编号) + * + * @param lineId 行编号 + * @return 委外收货明细列表 + */ + List getOutsourceReceiptDetailListByLineId(Long lineId); + + /** + * 删除委外收货明细(根据收货单编号) + * + * @param receiptId 收货单编号 + */ + void deleteOutsourceReceiptDetailByReceiptId(Long receiptId); + + /** + * 删除委外收货明细(根据行编号) + * + * @param lineId 行编号 + */ + void deleteOutsourceReceiptDetailByLineId(Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailServiceImpl.java new file mode 100644 index 000000000..60e4934fa --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailServiceImpl.java @@ -0,0 +1,124 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.detail.MesWmOutsourceReceiptDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt.MesWmOutsourceReceiptDetailMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_RECEIPT_DETAIL_NOT_EXISTS; + +/** + * MES 委外收货明细 Service 实现类 + */ +@Service +@Validated +public class MesWmOutsourceReceiptDetailServiceImpl implements MesWmOutsourceReceiptDetailService { + + @Resource + private MesWmOutsourceReceiptDetailMapper detailMapper; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesWmWarehouseService warehouseService; + + @Resource + private MesWmWarehouseLocationService locationService; + + @Resource + private MesWmWarehouseAreaService areaService; + + @Override + public Long createOutsourceReceiptDetail(MesWmOutsourceReceiptDetailSaveReqVO createReqVO) { + // 校验物料存在 + itemService.validateItemExists(createReqVO.getItemId()); + // 校验仓库、库区、库位存在 + if (createReqVO.getWarehouseId() != null) { + warehouseService.validateWarehouseExists(createReqVO.getWarehouseId()); + } + if (createReqVO.getLocationId() != null) { + locationService.validateWarehouseLocationExists(createReqVO.getLocationId()); + } + if (createReqVO.getAreaId() != null) { + areaService.validateWarehouseAreaExists(createReqVO.getAreaId()); + } + + // 插入 + MesWmOutsourceReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmOutsourceReceiptDetailDO.class); + detailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateOutsourceReceiptDetail(MesWmOutsourceReceiptDetailSaveReqVO updateReqVO) { + // 校验存在 + validateOutsourceReceiptDetailExists(updateReqVO.getId()); + // 校验物料存在 + itemService.validateItemExists(updateReqVO.getItemId()); + // 校验仓库、库区、库位存在 + if (updateReqVO.getWarehouseId() != null) { + warehouseService.validateWarehouseExists(updateReqVO.getWarehouseId()); + } + if (updateReqVO.getLocationId() != null) { + locationService.validateWarehouseLocationExists(updateReqVO.getLocationId()); + } + if (updateReqVO.getAreaId() != null) { + areaService.validateWarehouseAreaExists(updateReqVO.getAreaId()); + } + + // 更新 + MesWmOutsourceReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceReceiptDetailDO.class); + detailMapper.updateById(updateObj); + } + + @Override + public void deleteOutsourceReceiptDetail(Long id) { + // 校验存在 + validateOutsourceReceiptDetailExists(id); + // 删除 + detailMapper.deleteById(id); + } + + @Override + public MesWmOutsourceReceiptDetailDO getOutsourceReceiptDetail(Long id) { + return detailMapper.selectById(id); + } + + @Override + public List getOutsourceReceiptDetailListByReceiptId(Long receiptId) { + return detailMapper.selectListByReceiptId(receiptId); + } + + @Override + public List getOutsourceReceiptDetailListByLineId(Long lineId) { + return detailMapper.selectListByLineId(lineId); + } + + @Override + public void deleteOutsourceReceiptDetailByReceiptId(Long receiptId) { + detailMapper.deleteByReceiptId(receiptId); + } + + @Override + public void deleteOutsourceReceiptDetailByLineId(Long lineId) { + detailMapper.deleteByLineId(lineId); + } + + private void validateOutsourceReceiptDetailExists(Long id) { + if (detailMapper.selectById(id) == null) { + throw exception(WM_OUTSOURCE_RECEIPT_DETAIL_NOT_EXISTS); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineService.java new file mode 100644 index 000000000..278ee0162 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineService.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line.MesWmOutsourceReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line.MesWmOutsourceReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptLineDO; + +import java.util.List; + +/** + * MES 委外收货单行 Service 接口 + */ +public interface MesWmOutsourceReceiptLineService { + + /** + * 创建外协入库单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceReceiptLine(MesWmOutsourceReceiptLineSaveReqVO createReqVO); + + /** + * 更新外协入库单行 + * + * @param updateReqVO 更新信息 + */ + void updateOutsourceReceiptLine(MesWmOutsourceReceiptLineSaveReqVO updateReqVO); + + /** + * 删除外协入库单行 + * + * @param id 编号 + */ + void deleteOutsourceReceiptLine(Long id); + + /** + * 获得外协入库单行 + * + * @param id 编号 + * @return 外协入库单行 + */ + MesWmOutsourceReceiptLineDO getOutsourceReceiptLine(Long id); + + /** + * 获得外协入库单行分页 + * + * @param pageReqVO 分页查询 + * @return 外协入库单行分页 + */ + PageResult getOutsourceReceiptLinePage(MesWmOutsourceReceiptLinePageReqVO pageReqVO); + + /** + * 获得外协入库单行列表(根据入库单编号) + * + * @param receiptId 入库单编号 + * @return 外协入库单行列表 + */ + List getOutsourceReceiptLineListByReceiptId(Long receiptId); + + /** + * 删除外协入库单行(根据入库单编号) + * + * @param receiptId 入库单编号 + */ + void deleteOutsourceReceiptLineByReceiptId(Long receiptId); + + /** + * 直接更新外协入库单行 DO(用于 IQC 回写) + * + * @param line 行 DO + */ + void updateOutsourceReceiptLineDO(MesWmOutsourceReceiptLineDO line); + + /** + * 直接插入外协入库单行 DO(用于 QC 按质量拆分行) + * + * @param line 行 DO + */ + void createOutsourceReceiptLineDO(MesWmOutsourceReceiptLineDO line); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java new file mode 100644 index 000000000..2c81a7632 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java @@ -0,0 +1,180 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line.MesWmOutsourceReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.line.MesWmOutsourceReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt.MesWmOutsourceReceiptLineMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS; + +/** + * MES 委外收货单行 Service 实现类 + */ +@Service +@Validated +public class MesWmOutsourceReceiptLineServiceImpl implements MesWmOutsourceReceiptLineService { + + @Resource + private MesWmOutsourceReceiptLineMapper lineMapper; + + @Resource + private MesMdItemService itemService; + + @Resource + @Lazy + private MesWmOutsourceReceiptDetailService outsourceReceiptDetailService; + + @Resource + @Lazy + private MesWmOutsourceReceiptService outsourceReceiptService; + + @Resource + @Lazy + private MesProWorkOrderService workOrderService; + + @Resource + private MesWmBatchService batchService; + + @Override + public Long createOutsourceReceiptLine(MesWmOutsourceReceiptLineSaveReqVO createReqVO) { + // 校验物料存在 + itemService.validateItemExists(createReqVO.getItemId()); + + // 插入 + MesWmOutsourceReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmOutsourceReceiptLineDO.class); + line.setQualityStatus(calculateQualityStatus(line.getIqcCheckFlag())); // 质量状态自动赋值 + // 生成或获取批次 + MesWmBatchDO batch = generateOrGetBatch(createReqVO); + if (batch != null) { + line.setBatchId(batch.getId()); + line.setBatchCode(batch.getCode()); + } + lineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateOutsourceReceiptLine(MesWmOutsourceReceiptLineSaveReqVO updateReqVO) { + // 校验存在 + validateOutsourceReceiptLineExists(updateReqVO.getId()); + // 校验物料存在 + itemService.validateItemExists(updateReqVO.getItemId()); + + // 更新 + MesWmOutsourceReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceReceiptLineDO.class); + updateObj.setQualityStatus(calculateQualityStatus(updateObj.getIqcCheckFlag())); // 质量状态自动赋值 + // 生成或获取批次 + MesWmBatchDO batch = generateOrGetBatch(updateReqVO); + if (batch != null) { + updateObj.setBatchId(batch.getId()); + updateObj.setBatchCode(batch.getCode()); + } + lineMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteOutsourceReceiptLine(Long id) { + // 校验存在 + validateOutsourceReceiptLineExists(id); + + // 级联删除明细 + outsourceReceiptDetailService.deleteOutsourceReceiptDetailByLineId(id); + // 删除 + lineMapper.deleteById(id); + } + + @Override + public MesWmOutsourceReceiptLineDO getOutsourceReceiptLine(Long id) { + return lineMapper.selectById(id); + } + + @Override + public PageResult getOutsourceReceiptLinePage(MesWmOutsourceReceiptLinePageReqVO pageReqVO) { + return lineMapper.selectPage(pageReqVO); + } + + @Override + public List getOutsourceReceiptLineListByReceiptId(Long receiptId) { + return lineMapper.selectListByReceiptId(receiptId); + } + + @Override + public void deleteOutsourceReceiptLineByReceiptId(Long receiptId) { + lineMapper.deleteByReceiptId(receiptId); + } + + private void validateOutsourceReceiptLineExists(Long id) { + if (lineMapper.selectById(id) == null) { + throw exception(WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS); + } + } + + @Override + public void updateOutsourceReceiptLineDO(MesWmOutsourceReceiptLineDO line) { + lineMapper.updateById(line); + } + + @Override + public void createOutsourceReceiptLineDO(MesWmOutsourceReceiptLineDO line) { + lineMapper.insert(line); + } + + /** + * 根据 iqcCheckFlag,计算质量状态 + * + * @param iqcCheckFlag 是否需要质检 + * @return 质量状态 + */ + private Integer calculateQualityStatus(Boolean iqcCheckFlag) { + if (Boolean.TRUE.equals(iqcCheckFlag)) { + return MesWmQualityStatusEnum.PENDING.getStatus(); // 待检 + } + return MesWmQualityStatusEnum.PASS.getStatus(); // 不需检验,默认合格 + } + + /** + * 生成或获取批次 + * + * @param reqVO 入库单行请求VO + * @return 批次记录(如果物料未启用批次管理则返回 null) + */ + private MesWmBatchDO generateOrGetBatch(MesWmOutsourceReceiptLineSaveReqVO reqVO) { + MesWmBatchGenerateReqVO batchReqVO = new MesWmBatchGenerateReqVO(); + batchReqVO.setItemId(reqVO.getItemId()).setProduceDate(reqVO.getProductionDate()) + .setExpireDate(reqVO.getExpireDate()).setLotNumber(reqVO.getLotNumber()); + MesWmOutsourceReceiptDO receipt = outsourceReceiptService.getOutsourceReceipt(reqVO.getReceiptId()); + if (receipt != null) { + batchReqVO.setVendorId(receipt.getVendorId()) + .setWorkOrderId(receipt.getWorkOrderId()) + .setReceiptDate(receipt.getReceiptDate()); + if (receipt.getWorkOrderId() != null) { + MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(receipt.getWorkOrderId()); + if (workOrder != null) { + batchReqVO.setClientId(workOrder.getClientId()); + } + } + } + // 调用批次服务生成或获取批次 + return batchService.getOrGenerateBatchCode(batchReqVO); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java new file mode 100644 index 000000000..01b93990c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; + +/** + * MES 外协入库单 Service 接口 + */ +public interface MesWmOutsourceReceiptService { + + /** + * 创建外协入库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createOutsourceReceipt(@Valid MesWmOutsourceReceiptSaveReqVO createReqVO); + + /** + * 修改外协入库单 + * + * @param updateReqVO 修改信息 + */ + void updateOutsourceReceipt(@Valid MesWmOutsourceReceiptSaveReqVO updateReqVO); + + /** + * 删除外协入库单(级联删除行+明细) + * + * @param id 编号 + */ + void deleteOutsourceReceipt(Long id); + + /** + * 获得外协入库单 + * + * @param id 编号 + * @return 外协入库单 + */ + MesWmOutsourceReceiptDO getOutsourceReceipt(Long id); + + /** + * 获得外协入库单分页 + * + * @param pageReqVO 分页参数 + * @return 外协入库单分页 + */ + PageResult getOutsourceReceiptPage(MesWmOutsourceReceiptPageReqVO pageReqVO); + + /** + * 提交外协入库单(草稿 → 审批中) + * + * @param id 编号 + */ + void submitOutsourceReceipt(Long id); + + /** + * 执行上架(审批中 → 已审批) + * + * @param id 编号 + */ + void stockOutsourceReceipt(Long id); + + /** + * 完成入库(已审批 → 已完成),更新库存台账 + * + * @param id 编号 + */ + void finishOutsourceReceipt(Long id); + + /** + * 取消外协入库单(任意非已完成/已取消状态 → 已取消) + * + * @param id 编号 + */ + void cancelOutsourceReceipt(Long id); + + /** + * IQC 检验完成后回写外协入库单(拆分行 + 推进主表状态) + * + * @param receiptId 外协入库单编号 + * @param lineId 入库单行编号 + * @param iqcId IQC 检验单编号 + * @param qualifiedQuantity 合格品数量 + * @param unqualifiedQuantity 不合格品数量 + */ + void updateOutsourceReceiptWhenIqcFinish(Long receiptId, Long lineId, Long iqcId, + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity); + + /** + * 校验外协入库单和行存在 + * + * @param receiptId 入库单编号 + * @param lineId 行编号 + */ + void validateOutsourceReceiptAndLineExists(Long receiptId, Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java new file mode 100644 index 000000000..88270fbb5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java @@ -0,0 +1,328 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo.MesWmOutsourceReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt.MesWmOutsourceReceiptMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceReceiptStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 外协入库单 Service 实现类 + */ +@Service +@Validated +public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptService { + + @Resource + private MesWmOutsourceReceiptMapper outsourceReceiptMapper; + + @Resource + private MesWmOutsourceReceiptLineService outsourceReceiptLineService; + @Resource + private MesWmOutsourceReceiptDetailService outsourceReceiptDetailService; + @Resource + private MesWmTransactionService wmTransactionService; + @Resource + private MesMdVendorService vendorService; + @Resource + private MesMdItemService itemService; + @Resource + private MesProWorkOrderService workOrderService; + + @Override + public Long createOutsourceReceipt(MesWmOutsourceReceiptSaveReqVO createReqVO) { + // 校验编码唯一 + validateCodeUnique(null, createReqVO.getCode()); + // 校验供应商存在 + vendorService.validateVendorExists(createReqVO.getVendorId()); + // 校验外协工单存在 + if (createReqVO.getWorkOrderId() != null) { + workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); + } + + // 插入 + MesWmOutsourceReceiptDO receipt = BeanUtils.toBean(createReqVO, MesWmOutsourceReceiptDO.class); + receipt.setStatus(MesWmOutsourceReceiptStatusEnum.PREPARE.getStatus()); + outsourceReceiptMapper.insert(receipt); + return receipt.getId(); + } + + @Override + public void updateOutsourceReceipt(MesWmOutsourceReceiptSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateOutsourceReceiptExistsAndDraft(updateReqVO.getId()); + // 校验编码唯一 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + // 校验供应商存在 + vendorService.validateVendorExists(updateReqVO.getVendorId()); + // 校验外协工单存在 + if (updateReqVO.getWorkOrderId() != null) { + workOrderService.validateWorkOrderExists(updateReqVO.getWorkOrderId()); + } + + // 更新 + MesWmOutsourceReceiptDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceReceiptDO.class); + outsourceReceiptMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteOutsourceReceipt(Long id) { + // 校验存在 + 草稿状态 + validateOutsourceReceiptExistsAndDraft(id); + + // 级联删除明细和行 + outsourceReceiptDetailService.deleteOutsourceReceiptDetailByReceiptId(id); + outsourceReceiptLineService.deleteOutsourceReceiptLineByReceiptId(id); + // 删除 + outsourceReceiptMapper.deleteById(id); + } + + @Override + public MesWmOutsourceReceiptDO getOutsourceReceipt(Long id) { + return outsourceReceiptMapper.selectById(id); + } + + @Override + public PageResult getOutsourceReceiptPage(MesWmOutsourceReceiptPageReqVO pageReqVO) { + List workOrderIds = null; + if (StrUtil.isNotBlank(pageReqVO.getWorkOrderCode())) { + MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(pageReqVO.getWorkOrderCode()); + if (workOrder == null) { + return PageResult.empty(); + } + workOrderIds = java.util.Collections.singletonList(workOrder.getId()); + } + return outsourceReceiptMapper.selectPage(pageReqVO, workOrderIds); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitOutsourceReceipt(Long id) { + // 校验存在 + 草稿状态 + validateOutsourceReceiptExistsAndDraft(id); + // 校验至少有一条行 + List lines = outsourceReceiptLineService.getOutsourceReceiptLineListByReceiptId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_OUTSOURCE_RECEIPT_NO_LINE); + } + + // 检查是否有待检验的行 + boolean hasPendingQc = CollUtil.contains(lines, + line -> MesWmQualityStatusEnum.PENDING.getStatus().equals(line.getQualityStatus())); + // 根据质检状态,路由到待检验或待上架 + Integer targetStatus = hasPendingQc ? MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus() + : MesWmOutsourceReceiptStatusEnum.APPROVING.getStatus(); + outsourceReceiptMapper.updateById(new MesWmOutsourceReceiptDO() + .setId(id).setStatus(targetStatus)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockOutsourceReceipt(Long id) { + // 1.1 校验存在 + 待上架状态 + MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(id); + if (ObjUtil.notEqual(MesWmOutsourceReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus())) { + throw exception(WM_OUTSOURCE_RECEIPT_STATUS_ERROR); + } + // 1.2 检查每个行的明细数量是否完成上架 + List lines = outsourceReceiptLineService.getOutsourceReceiptLineListByReceiptId(id); + if (CollUtil.isNotEmpty(lines)) { + // 批量查询所有明细 + List allDetails = outsourceReceiptDetailService.getOutsourceReceiptDetailListByReceiptId(id); + Map> detailMap = CollectionUtils.convertMultiMap( + allDetails, MesWmOutsourceReceiptDetailDO::getLineId); + // 检查每行的明细数量 + for (MesWmOutsourceReceiptLineDO line : lines) { + List details = detailMap.getOrDefault(line.getId(), List.of()); + BigDecimal totalDetailQuantity = CollectionUtils.getSumValue(details, + MesWmOutsourceReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + // 对比行数量与明细总数量,不满足直接抛出 + if (line.getQuantity().compareTo(totalDetailQuantity) > 0) { + MesMdItemDO item = itemService.validateItemExists(line.getItemId()); + throw exception(WM_OUTSOURCE_RECEIPT_DETAIL_QUANTITY_MISMATCH, + item.getCode() + " " + item.getName() + " 未完成上架"); + } + } + } + + // 2. 入库上架(待上架 → 已审批) + outsourceReceiptMapper.updateById(new MesWmOutsourceReceiptDO() + .setId(id).setStatus(MesWmOutsourceReceiptStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishOutsourceReceipt(Long id) { + // 1.1 校验存在 + MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(id); + if (ObjUtil.notEqual(MesWmOutsourceReceiptStatusEnum.APPROVED.getStatus(), receipt.getStatus())) { + throw exception(WM_OUTSOURCE_RECEIPT_STATUS_ERROR); + } + // 1.2 校验至少有一条行 + List lines = outsourceReceiptLineService.getOutsourceReceiptLineListByReceiptId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_OUTSOURCE_RECEIPT_NO_LINE); + } + + // 3. 遍历所有明细,创建库存事务(增加库存 + 记录流水) + createTransactionList(receipt); + + // 4. 更新外协工单的已生产数量(只统计合格的目标产品) + if (receipt.getWorkOrderId() != null) { + MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(receipt.getWorkOrderId()); + if (workOrder != null) { + BigDecimal totalQuantity = lines.stream() + .filter(line -> ObjUtil.equal(line.getItemId(), workOrder.getProductId())) // 只统计目标产品 + .filter(line -> ObjUtil.notEqual(line.getQualityStatus(), MesWmQualityStatusEnum.FAIL.getStatus())) // 排除不合格品 + .map(MesWmOutsourceReceiptLineDO::getQuantity) + .reduce(BigDecimal.ZERO, BigDecimal::add); + if (totalQuantity.compareTo(BigDecimal.ZERO) > 0) { + workOrderService.updateProducedQuantity(receipt.getWorkOrderId(), totalQuantity); + } + } + } + + // 5. 更新入库单状态 + outsourceReceiptMapper.updateById(new MesWmOutsourceReceiptDO() + .setId(id).setStatus(MesWmOutsourceReceiptStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmOutsourceReceiptDO receipt) { + List details = outsourceReceiptDetailService.getOutsourceReceiptDetailListByReceiptId(receipt.getId()); + wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity()) // 入库数量为正数 + .setBatchId(detail.getBatchId()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setVendorId(receipt.getVendorId()).setReceiptTime(receipt.getReceiptDate()) + .setBizType(MesBizTypeConstants.WM_OUTSOURCE_RECPT).setBizId(receipt.getId()) + .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId()))); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelOutsourceReceipt(Long id) { + // 校验存在 + MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(receipt.getStatus(), + MesWmOutsourceReceiptStatusEnum.FINISHED.getStatus(), + MesWmOutsourceReceiptStatusEnum.CANCELED.getStatus())) { + throw exception(WM_OUTSOURCE_RECEIPT_CANCEL_NOT_ALLOWED); + } + // 取消 + outsourceReceiptMapper.updateById(new MesWmOutsourceReceiptDO() + .setId(id).setStatus(MesWmOutsourceReceiptStatusEnum.CANCELED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateOutsourceReceiptWhenIqcFinish(Long receiptId, Long lineId, Long iqcId, + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity) { + // 1.1 校验入库单存在 + MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(receiptId); + // 1.2 校验状态为待检验 + if (ObjUtil.notEqual(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus(), receipt.getStatus())) { + throw exception(WM_OUTSOURCE_RECEIPT_STATUS_ERROR); + } + // 1.3 校验行存在 + MesWmOutsourceReceiptLineDO line = outsourceReceiptLineService.getOutsourceReceiptLine(lineId); + if (line == null) { + throw exception(WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS); + } + + // 2.1 合格品处理:更新原行(new 一个 DO,避免覆盖更新) + if (qualifiedQuantity != null && qualifiedQuantity.compareTo(BigDecimal.ZERO) > 0) { + outsourceReceiptLineService.updateOutsourceReceiptLineDO(new MesWmOutsourceReceiptLineDO() + .setId(lineId).setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) + .setIqcId(iqcId).setQuantity(qualifiedQuantity)); + } + // 2.2 不合格品处理:拷贝原行全部属性,新增一行 + if (unqualifiedQuantity != null && unqualifiedQuantity.compareTo(BigDecimal.ZERO) > 0) { + MesWmOutsourceReceiptLineDO unqualifiedLine = BeanUtils.toBean(line, MesWmOutsourceReceiptLineDO.class) + .setId(null).setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) + .setIqcId(iqcId).setQuantity(unqualifiedQuantity); + outsourceReceiptLineService.createOutsourceReceiptLineDO(unqualifiedLine); + } + + // 3. 直接更新主表状态为"待上架" + outsourceReceiptMapper.updateById(new MesWmOutsourceReceiptDO() + .setId(receiptId).setStatus(MesWmOutsourceReceiptStatusEnum.APPROVING.getStatus())); + } + + private MesWmOutsourceReceiptDO validateOutsourceReceiptExists(Long id) { + MesWmOutsourceReceiptDO receipt = outsourceReceiptMapper.selectById(id); + if (receipt == null) { + throw exception(WM_OUTSOURCE_RECEIPT_NOT_EXISTS); + } + return receipt; + } + + @Override + public void validateOutsourceReceiptAndLineExists(Long receiptId, Long lineId) { + // 1. 校验入库单存在 + validateOutsourceReceiptExists(receiptId); + // 2. 校验行存在且属于该入库单 + MesWmOutsourceReceiptLineDO line = outsourceReceiptLineService.getOutsourceReceiptLine(lineId); + if (line == null) { + throw exception(WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS); + } + if (ObjUtil.notEqual(receiptId, line.getReceiptId())) { + throw exception(WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS); + } + } + + /** + * 校验外协入库单存在且为草稿状态 + */ + private MesWmOutsourceReceiptDO validateOutsourceReceiptExistsAndDraft(Long id) { + MesWmOutsourceReceiptDO receipt = validateOutsourceReceiptExists(id); + if (ObjUtil.notEqual(MesWmOutsourceReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())) { + throw exception(WM_OUTSOURCE_RECEIPT_STATUS_NOT_PREPARE); + } + return receipt; + } + + private void validateCodeUnique(Long id, String code) { + MesWmOutsourceReceiptDO receipt = outsourceReceiptMapper.selectByCode(code); + if (receipt == null) { + return; + } + if (ObjUtil.notEqual(id, receipt.getId())) { + throw exception(WM_OUTSOURCE_RECEIPT_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineService.java new file mode 100644 index 000000000..5a932220b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineService.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.mes.service.wm.packages; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPackageLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPackageLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO; +import jakarta.validation.Valid; + +/** + * MES 装箱明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmPackageLineService { + + /** + * 创建装箱明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPackageLine(@Valid MesWmPackageLineSaveReqVO createReqVO); + + /** + * 修改装箱明细 + * + * @param updateReqVO 修改信息 + */ + void updatePackageLine(@Valid MesWmPackageLineSaveReqVO updateReqVO); + + /** + * 删除装箱明细 + * + * @param id 编号 + */ + void deletePackageLine(Long id); + + /** + * 获得装箱明细 + * + * @param id 编号 + * @return 装箱明细 + */ + MesWmPackageLineDO getPackageLine(Long id); + + /** + * 获得装箱明细分页 + * + * @param pageReqVO 分页查询 + * @return 分页结果 + */ + PageResult getPackageLinePage(MesWmPackageLinePageReqVO pageReqVO); + + /** + * 根据装箱单 ID 删除所有明细 + * + * @param packageId 装箱单 ID + */ + void deletePackageLineByPackageId(Long packageId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineServiceImpl.java new file mode 100644 index 000000000..4be0675d0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineServiceImpl.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.service.wm.packages; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPackageLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPackageLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.packages.MesWmPackageLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PACKAGE_LINE_NOT_EXISTS; + +/** + * MES 装箱明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmPackageLineServiceImpl implements MesWmPackageLineService { + + @Resource + private MesWmPackageLineMapper packageLineMapper; + @Resource + @Lazy + private MesWmPackageService packageService; + @Resource + private MesMdItemService itemService; + + @Override + public Long createPackageLine(MesWmPackageLineSaveReqVO createReqVO) { + // 校验装箱单状态为草稿 + packageService.validatePackageStatusDraft(createReqVO.getPackageId()); + // 校验产品物料存在 + itemService.validateItemExists(createReqVO.getItemId()); + + // 插入 + MesWmPackageLineDO line = BeanUtils.toBean(createReqVO, MesWmPackageLineDO.class); + packageLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updatePackageLine(MesWmPackageLineSaveReqVO updateReqVO) { + // 校验存在 + MesWmPackageLineDO line = validatePackageLineExists(updateReqVO.getId()); + // 校验装箱单状态为草稿 + packageService.validatePackageStatusDraft(line.getPackageId()); + // 校验产品物料存在 + itemService.validateItemExists(updateReqVO.getItemId()); + + // 更新 + MesWmPackageLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmPackageLineDO.class); + packageLineMapper.updateById(updateObj); + } + + @Override + public void deletePackageLine(Long id) { + // 校验存在 + MesWmPackageLineDO line = validatePackageLineExists(id); + // 校验装箱单状态为草稿 + packageService.validatePackageStatusDraft(line.getPackageId()); + + // 删除 + packageLineMapper.deleteById(id); + } + + @Override + public MesWmPackageLineDO getPackageLine(Long id) { + return packageLineMapper.selectById(id); + } + + @Override + public PageResult getPackageLinePage(MesWmPackageLinePageReqVO pageReqVO) { + if (pageReqVO.getPackageId() == null) { + return PageResult.empty(); + } + List packageIds = packageService.getPackageAndDescendantIds(pageReqVO.getPackageId()); + return packageLineMapper.selectPage(pageReqVO, packageIds); + } + + @Override + public void deletePackageLineByPackageId(Long packageId) { + packageLineMapper.deleteByPackageId(packageId); + } + + // ========== 校验方法 ========== + + private MesWmPackageLineDO validatePackageLineExists(Long id) { + MesWmPackageLineDO line = packageLineMapper.selectById(id); + if (line == null) { + throw exception(WM_PACKAGE_LINE_NOT_EXISTS); + } + return line; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageService.java new file mode 100644 index 000000000..aab8124c9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageService.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.mes.service.wm.packages; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 装箱单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmPackageService { + + /** + * 创建装箱单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPackage(@Valid MesWmPackageSaveReqVO createReqVO); + + /** + * 修改装箱单 + * + * @param updateReqVO 修改信息 + */ + void updatePackage(@Valid MesWmPackageSaveReqVO updateReqVO); + + /** + * 删除装箱单 + * + * @param id 编号 + */ + void deletePackage(Long id); + + /** + * 获得装箱单 + * + * @param id 编号 + * @return 装箱单 + */ + MesWmPackageDO getPackage(Long id); + + /** + * 获得装箱单分页 + * + * @param pageReqVO 分页查询 + * @return 分页结果 + */ + PageResult getPackagePage(MesWmPackagePageReqVO pageReqVO); + + /** + * 完成装箱单 + * + * @param id 编号 + */ + void finishPackage(Long id); + + /** + * 校验装箱单状态为草稿 + * + * @param packageId 装箱单 ID + */ + void validatePackageStatusDraft(Long packageId); + + /** + * 添加子箱 + * + * @param parentId 父箱 ID + * @param childId 子箱 ID + */ + void addChildPackage(Long parentId, Long childId); + + /** + * 移除子箱 + * + * @param childId 子箱 ID + */ + void removeChildPackage(Long childId); + + /** + * 可添加为子箱的装箱单列表(无父箱 + 已完成状态) + * + * @return 装箱单列表 + */ + List getChildablePackageList(); + + /** + * 获得装箱单精简列表 + * + * @return 装箱单列表 + */ + List getPackageSimpleList(); + + /** + * 获取指定装箱单及其所有子孙箱的 ID 列表 + * + * @param packageId 装箱单 ID + * @return 装箱单及其所有子孙箱的 ID 集合 + */ + List getPackageAndDescendantIds(Long packageId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java new file mode 100644 index 000000000..24a206fce --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java @@ -0,0 +1,232 @@ +package cn.iocoder.yudao.module.mes.service.wm.packages; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.packages.MesWmPackageMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmPackageStatusEnum; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 装箱单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmPackageServiceImpl implements MesWmPackageService { + + @Resource + private MesWmPackageMapper packageMapper; + @Resource + private MesWmPackageLineService packageLineService; + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createPackage(MesWmPackageSaveReqVO createReqVO) { + // 校验编码唯一性 + validateCodeUnique(null, createReqVO.getCode()); + + // 创建装箱单,默认为草稿状态 + MesWmPackageDO packageDO = BeanUtils.toBean(createReqVO, MesWmPackageDO.class); + packageDO.setStatus(MesWmPackageStatusEnum.PREPARE.getStatus()) + .setParentId(MesWmPackageDO.PARENT_ID_ROOT); + packageMapper.insert(packageDO); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.PACKAGE.getValue(), + packageDO.getId(), packageDO.getCode(), null); + return packageDO.getId(); + } + + @Override + public void updatePackage(MesWmPackageSaveReqVO updateReqVO) { + // 校验存在且为草稿 + validatePackageExistsAndDraft(updateReqVO.getId()); + // 校验编码唯一性 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新装箱单 + MesWmPackageDO updateObj = BeanUtils.toBean(updateReqVO, MesWmPackageDO.class); + packageMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePackage(Long id) { + // 校验存在且为草稿 + validatePackageExistsAndDraft(id); + // 如果有子箱子,不允许删除 + List children = packageMapper.selectListByParentId(id); + if (CollUtil.isNotEmpty(children)) { + throw exception(WM_PACKAGE_HAS_CHILDREN); + } + + // 删除装箱单 + packageMapper.deleteById(id); + // 删除装箱明细 + packageLineService.deletePackageLineByPackageId(id); + } + + @Override + public MesWmPackageDO getPackage(Long id) { + return packageMapper.selectById(id); + } + + @Override + public PageResult getPackagePage(MesWmPackagePageReqVO pageReqVO) { + return packageMapper.selectPage(pageReqVO); + } + + @Override + public void finishPackage(Long id) { + // 校验存在且为草稿 + validatePackageExistsAndDraft(id); + + // 更新状态为已完成 + packageMapper.updateById(new MesWmPackageDO() + .setId(id).setStatus(MesWmPackageStatusEnum.FINISHED.getStatus())); + } + + @Override + public void validatePackageStatusDraft(Long packageId) { + validatePackageExistsAndDraft(packageId); + } + + @Override + public void addChildPackage(Long parentId, Long childId) { + // 校验父箱存在且为草稿 + validatePackageExistsAndDraft(parentId); + // 校验子箱存在 + MesWmPackageDO child = validatePackageExists(childId); + // 校验添加子箱的合法性 + validateAddChildPackage(parentId, child); + + // 设置子箱的 parentId + packageMapper.updateById(new MesWmPackageDO().setId(childId).setParentId(parentId)); + } + + @Override + public void removeChildPackage(Long childId) { + // 校验子箱存在 + MesWmPackageDO child = validatePackageExists(childId); + // 校验父箱存在且为草稿 + if (child.getParentId() != null + && ObjUtil.notEqual(child.getParentId(), MesWmPackageDO.PARENT_ID_ROOT)) { + validatePackageExistsAndDraft(child.getParentId()); + } + + // 清除 parentId + packageMapper.updateById(new MesWmPackageDO().setId(childId).setParentId(MesWmPackageDO.PARENT_ID_ROOT)); + } + + @Override + public List getChildablePackageList() { + return packageMapper.selectChildableList(); + } + + @Override + public List getPackageSimpleList() { + return packageMapper.selectList(); + } + + @Override + public List getPackageAndDescendantIds(Long packageId) { + List result = CollUtil.newArrayList(packageId); + // 使用广度优先搜索 (BFS) 按层批量查询所有子孙箱 ID + List currentLevelIds = CollUtil.newArrayList(packageId); + for (int i = 0; i < Short.MAX_VALUE && CollUtil.isNotEmpty(currentLevelIds); i++) { + List children = packageMapper.selectListByParentIds(currentLevelIds); + if (CollUtil.isEmpty(children)) { + break; + } + currentLevelIds = convertList(children, MesWmPackageDO::getId); + result.addAll(currentLevelIds); + } + return result; + } + + // ========== 校验方法 ========== + + private MesWmPackageDO validatePackageExists(Long id) { + MesWmPackageDO packageDO = packageMapper.selectById(id); + if (packageDO == null) { + throw exception(WM_PACKAGE_NOT_EXISTS); + } + return packageDO; + } + + private MesWmPackageDO validatePackageExistsAndDraft(Long id) { + MesWmPackageDO packageDO = validatePackageExists(id); + if (ObjUtil.notEqual(MesWmPackageStatusEnum.PREPARE.getStatus(), packageDO.getStatus())) { + throw exception(WM_PACKAGE_STATUS_NOT_PREPARE); + } + return packageDO; + } + + private void validateCodeUnique(Long id, String code) { + MesWmPackageDO packageDO = packageMapper.selectByCode(code); + if (packageDO == null) { + return; + } + if (ObjUtil.notEqual(id, packageDO.getId())) { + throw exception(WM_PACKAGE_CODE_DUPLICATE); + } + } + + /** + * 校验添加子箱的合法性 + * + * @param parentId 父箱 ID + * @param child 子箱 DO + */ + private void validateAddChildPackage(Long parentId, MesWmPackageDO child) { + // 1. 不能将自己作为子箱 + if (ObjUtil.equal(parentId, child.getId())) { + throw exception(WM_PACKAGE_PARENT_SELF); + } + // 2. 子箱没有父箱(parentId 为 0) + if (ObjUtil.notEqual(child.getParentId(), MesWmPackageDO.PARENT_ID_ROOT)) { + throw exception(WM_PACKAGE_CHILD_HAS_PARENT); + } + // 3. 子箱必须是已完成状态 + if (ObjUtil.notEqual(MesWmPackageStatusEnum.FINISHED.getStatus(), child.getStatus())) { + throw exception(WM_PACKAGE_CHILD_NOT_FINISHED); + } + // 4. 递归校验:确保 childId 不是 parentId 的祖先(避免形成环路) + MesWmPackageDO parentPackage = packageMapper.selectById(parentId); + for (int i = 0; i < Short.MAX_VALUE; i++) { + if (parentPackage == null) { + break; + } + // 4.1 校验环路 + parentId = parentPackage.getParentId(); + if (Objects.equals(child.getId(), parentId)) { + throw exception(WM_PACKAGE_PARENT_IS_CHILD); + } + // 4.2 继续递归下一级父箱 + if (parentId == null || MesWmPackageDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentPackage = packageMapper.selectById(parentId); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailService.java new file mode 100644 index 000000000..757fa16bb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailService.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.service.wm.productissue; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.detail.MesWmProductIssueDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 领料出库明细 Service 接口 + */ +public interface MesWmProductIssueDetailService { + + /** + * 创建领料出库明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductIssueDetail(@Valid MesWmProductIssueDetailSaveReqVO createReqVO); + + /** + * 更新领料出库明细 + * + * @param updateReqVO 更新信息 + */ + void updateProductIssueDetail(@Valid MesWmProductIssueDetailSaveReqVO updateReqVO); + + /** + * 删除领料出库明细 + * + * @param id 编号 + */ + void deleteProductIssueDetail(Long id); + + /** + * 获得领料出库明细 + * + * @param id 编号 + * @return 领料出库明细 + */ + MesWmProductIssueDetailDO getProductIssueDetail(Long id); + + /** + * 根据行ID获取明细列表 + * + * @param lineId 行ID + * @return 明细列表 + */ + List getProductIssueDetailListByLineId(Long lineId); + + /** + * 根据领料单ID获取明细列表 + * + * @param issueId 领料单ID + * @return 明细列表 + */ + List getProductIssueDetailListByIssueId(Long issueId); + + /** + * 根据领料单ID删除明细 + * + * @param issueId 领料单ID + */ + void deleteProductIssueDetailByIssueId(Long issueId); + + /** + * 根据行ID删除明细 + * + * @param lineId 行ID + */ + void deleteProductIssueDetailByLineId(Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java new file mode 100644 index 000000000..be75e99d6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.mes.service.wm.productissue; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.detail.MesWmProductIssueDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue.MesWmProductIssueDetailMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductIssueStatusEnum; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 领料出库明细 Service 实现类 + */ +@Service +@Validated +public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDetailService { + + @Resource + private MesWmProductIssueDetailMapper issueDetailMapper; + + @Resource + @Lazy + private MesWmProductIssueService issueService; + @Resource + @Lazy + private MesWmProductIssueLineService issueLineService; + + @Override + public Long createProductIssueDetail(MesWmProductIssueDetailSaveReqVO createReqVO) { + // 校验数据 + validateProductIssueDetailSaveData(createReqVO); + + // 插入 + MesWmProductIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmProductIssueDetailDO.class); + issueDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateProductIssueDetail(MesWmProductIssueDetailSaveReqVO updateReqVO) { + // 校验存在 + validateProductIssueDetailExists(updateReqVO.getId()); + // 校验数据 + validateProductIssueDetailSaveData(updateReqVO); + + // 更新 + MesWmProductIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueDetailDO.class); + issueDetailMapper.updateById(updateObj); + } + + @Override + public void deleteProductIssueDetail(Long id) { + // 校验存在 + MesWmProductIssueDetailDO detail = issueDetailMapper.selectById(id); + if (detail == null) { + throw exception(WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS); + } + // 校验主单状态为草稿或待拣货(允许在拣货模式删除明细) + MesWmProductIssueLineDO line = issueLineService.validateProductIssueLineExists(detail.getLineId()); + MesWmProductIssueDO issue = issueService.validateProductIssueExists(line.getIssueId()); + if (!ObjectUtils.equalsAny(issue.getStatus(), + MesWmProductIssueStatusEnum.PREPARE.getStatus(), + MesWmProductIssueStatusEnum.APPROVING.getStatus())) { + throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); + } + + // 删除 + issueDetailMapper.deleteById(id); + } + + @Override + public MesWmProductIssueDetailDO getProductIssueDetail(Long id) { + return issueDetailMapper.selectById(id); + } + + @Override + public List getProductIssueDetailListByLineId(Long lineId) { + return issueDetailMapper.selectListByLineId(lineId); + } + + @Override + public List getProductIssueDetailListByIssueId(Long issueId) { + return issueDetailMapper.selectListByIssueId(issueId); + } + + @Override + public void deleteProductIssueDetailByIssueId(Long issueId) { + issueDetailMapper.deleteByIssueId(issueId); + } + + @Override + public void deleteProductIssueDetailByLineId(Long lineId) { + issueDetailMapper.deleteByLineId(lineId); + } + + private void validateProductIssueDetailExists(Long id) { + if (issueDetailMapper.selectById(id) == null) { + throw exception(WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS); + } + } + + /** + * 校验保存时的关联数据 + */ + private void validateProductIssueDetailSaveData(MesWmProductIssueDetailSaveReqVO reqVO) { + // 校验父数据存在 + MesWmProductIssueLineDO line = issueLineService.validateProductIssueLineExists(reqVO.getLineId()); + // 校验物料匹配(明细 itemId 必须与行 itemId 一致) + validateDetailItemMatch(reqVO.getItemId(), line.getItemId()); + } + + /** + * 校验明细物料与行物料一致 + */ + private void validateDetailItemMatch(Long detailItemId, Long lineItemId) { + if (ObjUtil.notEqual(detailItemId, lineItemId)) { + throw exception(WM_PRODUCT_ISSUE_DETAIL_ITEM_MISMATCH); + } + } + +} + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineService.java new file mode 100644 index 000000000..ab9b47d0e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineService.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.mes.service.wm.productissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 领料出库单行 Service 接口 + */ +public interface MesWmProductIssueLineService { + + /** + * 创建领料出库单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductIssueLine(@Valid MesWmProductIssueLineSaveReqVO createReqVO); + + /** + * 更新领料出库单行 + * + * @param updateReqVO 更新信息 + */ + void updateProductIssueLine(@Valid MesWmProductIssueLineSaveReqVO updateReqVO); + + /** + * 删除领料出库单行 + * + * @param id 编号 + */ + void deleteProductIssueLine(Long id); + + /** + * 获得领料出库单行 + * + * @param id 编号 + * @return 领料出库单行 + */ + MesWmProductIssueLineDO getProductIssueLine(Long id); + + /** + * 获得领料出库单行分页 + * + * @param pageReqVO 分页查询 + * @return 领料出库单行分页 + */ + PageResult getProductIssueLinePage(MesWmProductIssueLinePageReqVO pageReqVO); + + /** + * 根据领料单ID获取行列表 + * + * @param issueId 领料单ID + * @return 行列表 + */ + List getProductIssueLineListByIssueId(Long issueId); + + /** + * 根据领料单ID删除行 + * + * @param issueId 领料单ID + */ + void deleteProductIssueLineByIssueId(Long issueId); + + /** + * 校验领料出库单行是否存在 + * + * @param id 编号 + * @return 领料出库单行 + */ + MesWmProductIssueLineDO validateProductIssueLineExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java new file mode 100644 index 000000000..4612b6099 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.mes.service.wm.productissue; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.line.MesWmProductIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue.MesWmProductIssueLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderBomService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_ISSUE_LINE_ITEM_NOT_IN_BOM; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_ISSUE_LINE_NOT_EXISTS; + +/** + * MES 领料出库单行 Service 实现类 + */ +@Service +@Validated +public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineService { + + @Resource + private MesWmProductIssueLineMapper issueLineMapper; + + @Resource + @Lazy + private MesWmProductIssueService issueService; + @Resource + private MesMdItemService itemService; + @Resource + private MesProWorkOrderBomService workOrderBomService; + @Resource + @Lazy + private MesWmProductIssueDetailService issueDetailService; + + @Override + public Long createProductIssueLine(MesWmProductIssueLineSaveReqVO createReqVO) { + validateProductIssueLineSaveData(createReqVO); + + // 插入 + MesWmProductIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmProductIssueLineDO.class); + issueLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateProductIssueLine(MesWmProductIssueLineSaveReqVO updateReqVO) { + // 校验存在 + validateProductIssueLineExists(updateReqVO.getId()); + validateProductIssueLineSaveData(updateReqVO); + + // 更新 + MesWmProductIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueLineDO.class); + issueLineMapper.updateById(updateObj); + } + + @Override + public void deleteProductIssueLine(Long id) { + // 校验存在 + MesWmProductIssueLineDO line = validateProductIssueLineExists(id); + // 校验主单为草稿状态才允许删除行 + issueService.validateProductIssueExistsAndPrepare(line.getIssueId()); + // 级联删除该行的明细 + issueDetailService.deleteProductIssueDetailByLineId(id); + // 删除行 + issueLineMapper.deleteById(id); + } + + @Override + public MesWmProductIssueLineDO getProductIssueLine(Long id) { + return issueLineMapper.selectById(id); + } + + @Override + public PageResult getProductIssueLinePage(MesWmProductIssueLinePageReqVO pageReqVO) { + return issueLineMapper.selectPage(pageReqVO); + } + + @Override + public List getProductIssueLineListByIssueId(Long issueId) { + return issueLineMapper.selectListByIssueId(issueId); + } + + @Override + public void deleteProductIssueLineByIssueId(Long issueId) { + issueLineMapper.deleteByIssueId(issueId); + } + + @Override + public MesWmProductIssueLineDO validateProductIssueLineExists(Long id) { + MesWmProductIssueLineDO line = issueLineMapper.selectById(id); + if (line == null) { + throw exception(WM_PRODUCT_ISSUE_LINE_NOT_EXISTS); + } + return line; + } + + /** + * 校验保存时的关联数据 + */ + private void validateProductIssueLineSaveData(MesWmProductIssueLineSaveReqVO reqVO) { + // 校验父数据存在 + 校验物料在工单 BOM 中 + validateItemInWorkOrderBom(reqVO.getIssueId(), reqVO.getItemId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + } + + private void validateItemInWorkOrderBom(Long issueId, Long itemId) { + // 校验领料单存在,并获取工单编号 + MesWmProductIssueDO issue = issueService.validateProductIssueExists(issueId); + // 校验物料是否在工单 BOM 中(防错料) + List workOrderBoms = workOrderBomService.getWorkOrderBomListByWorkOrderId(issue.getWorkOrderId()); + if (CollUtil.isEmpty(workOrderBoms)) { + return; + } + MesProWorkOrderBomDO workOrderBom = CollUtil.findOne(workOrderBoms, + bom -> bom.getItemId().equals(itemId)); + if (workOrderBom == null) { + throw exception(WM_PRODUCT_ISSUE_LINE_ITEM_NOT_IN_BOM); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueService.java new file mode 100644 index 000000000..3ed9ecb27 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueService.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.service.wm.productissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO; +import jakarta.validation.Valid; + +/** + * MES 领料出库单 Service 接口 + */ +public interface MesWmProductIssueService { + + /** + * 创建领料出库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductIssue(@Valid MesWmProductIssueSaveReqVO createReqVO); + + /** + * 修改领料出库单 + * + * @param updateReqVO 修改信息 + */ + void updateProductIssue(@Valid MesWmProductIssueSaveReqVO updateReqVO); + + /** + * 删除领料出库单 + * + * @param id 编号 + */ + void deleteProductIssue(Long id); + + /** + * 获得领料出库单 + * + * @param id 编号 + * @return 领料出库单 + */ + MesWmProductIssueDO getProductIssue(Long id); + + /** + * 获得领料出库单分页 + * + * @param pageReqVO 分页参数 + * @return 领料出库单分页 + */ + PageResult getProductIssuePage(MesWmProductIssuePageReqVO pageReqVO); + + /** + * 校验领料出库单是否存在 + * + * @param id 编号 + * @return 领料出库单 + */ + MesWmProductIssueDO validateProductIssueExists(Long id); + + /** + * 校验领料出库单存在且为准备中状态 + * + * @param id 编号 + * @return 领料出库单 + */ + MesWmProductIssueDO validateProductIssueExistsAndPrepare(Long id); + + /** + * 提交领料出库单(草稿 → 待拣货) + * + * @param id 编号 + */ + void submitProductIssue(Long id); + + /** + * 执行拣货(待拣货 → 待执行领出) + * + * @param id 编号 + */ + void stockProductIssue(Long id); + + /** + * 执行领出/出库(待执行领出 → 已完成),更新库存台账 + * + * @param id 编号 + */ + void finishProductIssue(Long id); + + /** + * 取消领料出库单(任意非已完成/已取消状态 → 已取消) + * + * @param id 编号 + */ + void cancelProductIssue(Long id); + + /** + * 校验领料出库单的数量:每行明细数量之和是否等于行领料数量 + * + * @param id 编号 + * @return 是否全部一致 + */ + Boolean checkProductIssueQuantity(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java new file mode 100644 index 000000000..ea45bf331 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java @@ -0,0 +1,269 @@ +package cn.iocoder.yudao.module.mes.service.wm.productissue; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo.MesWmProductIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue.MesWmProductIssueMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductIssueStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 领料出库单 Service 实现类 + */ +@Service +@Validated +public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { + + @Resource + private MesWmProductIssueMapper issueMapper; + + @Resource + private MesWmProductIssueLineService issueLineService; + @Resource + private MesWmProductIssueDetailService issueDetailService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesWmTransactionService wmTransactionService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createProductIssue(MesWmProductIssueSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateProductIssueSaveData(createReqVO); + + // 2. 插入主表 + MesWmProductIssueDO issue = BeanUtils.toBean(createReqVO, MesWmProductIssueDO.class); + issue.setStatus(MesWmProductIssueStatusEnum.PREPARE.getStatus()); + issueMapper.insert(issue); + return issue.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateProductIssue(MesWmProductIssueSaveReqVO updateReqVO) { + // 1.1 校验存在 + 准备中状态 + validateProductIssueExistsAndPrepare(updateReqVO.getId()); + // 1.2 校验关联数据 + validateProductIssueSaveData(updateReqVO); + + // 2. 更新主表 + MesWmProductIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductIssueDO.class); + issueMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteProductIssue(Long id) { + // 1. 校验存在 + 准备中状态 + validateProductIssueExistsAndPrepare(id); + + // 2.1 级联删除明细 + issueDetailService.deleteProductIssueDetailByIssueId(id); + // 2.2 级联删除行 + issueLineService.deleteProductIssueLineByIssueId(id); + // 2.3 删除主表 + issueMapper.deleteById(id); + } + + @Override + public MesWmProductIssueDO getProductIssue(Long id) { + return issueMapper.selectById(id); + } + + @Override + public PageResult getProductIssuePage(MesWmProductIssuePageReqVO pageReqVO) { + return issueMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitProductIssue(Long id) { + // 校验存在 + 草稿状态 + validateProductIssueExistsAndPrepare(id); + // 校验至少有一条行 + List lines = issueLineService.getProductIssueLineListByIssueId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_PRODUCT_ISSUE_NO_LINE); + } + + // 提交(草稿 → 待拣货) + issueMapper.updateById(new MesWmProductIssueDO() + .setId(id).setStatus(MesWmProductIssueStatusEnum.APPROVING.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockProductIssue(Long id) { + // 校验存在 + MesWmProductIssueDO issue = validateProductIssueExists(id); + if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.APPROVING.getStatus(), issue.getStatus())) { + throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); + } + // 执行拣货(待拣货 → 待执行领出) + issueMapper.updateById(new MesWmProductIssueDO() + .setId(id).setStatus(MesWmProductIssueStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishProductIssue(Long id) { + // 1. 校验存在 + MesWmProductIssueDO issue = validateProductIssueExists(id); + if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.APPROVED.getStatus(), issue.getStatus())) { + throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); + } + + // 2. 遍历所有明细,创建库存事务(扣减库存 + 记录流水) + createTransactionList(issue); + + // 3. 更新出库单状态 + 领料日期 + issueMapper.updateById(new MesWmProductIssueDO() + .setId(id).setStatus(MesWmProductIssueStatusEnum.FINISHED.getStatus()) + .setIssueDate(LocalDateTime.now())); + } + + private void createTransactionList(MesWmProductIssueDO issue) { + // 1. 查询虚拟线边库 + MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); + + // 2. 遍历明细,每条明细产生 OUT(实际仓库扣减)+ IN(虚拟线边库增加) + List details = issueDetailService.getProductIssueDetailListByIssueId(issue.getId()); + for (MesWmProductIssueDetailDO detail : details) { + // 2.1 先从实际仓库出库(库存减少) + Long outTransactionId = wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity().negate()) // 库存减少 + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setBizType(MesBizTypeConstants.WM_ISSUE).setBizId(issue.getId()) + .setBizCode(issue.getCode()).setBizLineId(detail.getLineId())); + // 2.2 再入虚拟线边库(库存增加) + wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity()) // 库存增加 + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) + .setWarehouseId(virtualWarehouse.getId()).setLocationId(virtualLocation.getId()).setAreaId(virtualArea.getId()) + .setBizType(MesBizTypeConstants.WM_ISSUE).setBizId(issue.getId()) + .setBizCode(issue.getCode()).setBizLineId(detail.getLineId()) + .setRelatedTransactionId(outTransactionId)); // 关联出库事务 + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelProductIssue(Long id) { + // 校验存在 + MesWmProductIssueDO issue = validateProductIssueExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(issue.getStatus(), + MesWmProductIssueStatusEnum.FINISHED.getStatus(), + MesWmProductIssueStatusEnum.CANCELED.getStatus())) { + throw exception(WM_PRODUCT_ISSUE_CANCEL_NOT_ALLOWED); + } + + // 取消 + issueMapper.updateById(new MesWmProductIssueDO() + .setId(id).setStatus(MesWmProductIssueStatusEnum.CANCELED.getStatus())); + } + + @Override + public Boolean checkProductIssueQuantity(Long id) { + List lines = issueLineService.getProductIssueLineListByIssueId(id); + for (MesWmProductIssueLineDO line : lines) { + List details = issueDetailService.getProductIssueDetailListByLineId(line.getId()); + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmProductIssueDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) { + return false; + } + } + return true; + } + + @Override + public MesWmProductIssueDO validateProductIssueExists(Long id) { + MesWmProductIssueDO issue = issueMapper.selectById(id); + if (issue == null) { + throw exception(WM_PRODUCT_ISSUE_NOT_EXISTS); + } + return issue; + } + + /** + * 校验领料出库单存在且为准备中状态 + */ + @Override + public MesWmProductIssueDO validateProductIssueExistsAndPrepare(Long id) { + MesWmProductIssueDO issue = validateProductIssueExists(id); + if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) { + throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); + } + return issue; + } + + /** + * 校验编码唯一性 + */ + private void validateCodeUnique(Long id, String code) { + MesWmProductIssueDO issue = issueMapper.selectByCode(code); + if (issue == null) { + return; + } + if (ObjUtil.notEqual(id, issue.getId())) { + throw exception(WM_PRODUCT_ISSUE_CODE_DUPLICATE); + } + } + + /** + * 校验保存时的关联数据 + */ + private void validateProductIssueSaveData(MesWmProductIssueSaveReqVO reqVO) { + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + if (reqVO.getWorkstationId() != null) { + workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceDetailService.java new file mode 100644 index 000000000..d0dbdbc46 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceDetailService.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.mes.service.wm.productproduce; + +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; + +import java.util.List; + +/** + * MES 生产入库明细 Service 接口 + */ +public interface MesWmProductProduceDetailService { + + /** + * 创建生产入库明细(内部使用) + * + * @param detail 明细数据 + */ + void createProductProduceDetail(MesWmProductProduceDetailDO detail); + + /** + * 根据行ID获取明细列表 + * + * @param lineId 行ID + * @return 明细列表 + */ + List getProductProduceDetailListByLineId(Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceDetailServiceImpl.java new file mode 100644 index 000000000..efe8ff993 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceDetailServiceImpl.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.mes.service.wm.productproduce; + +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceDetailMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +/** + * MES 生产入库明细 Service 实现类 + */ +@Service +@Validated +public class MesWmProductProduceDetailServiceImpl implements MesWmProductProduceDetailService { + + @Resource + private MesWmProductProduceDetailMapper productProduceDetailMapper; + + @Override + public void createProductProduceDetail(MesWmProductProduceDetailDO detail) { + productProduceDetailMapper.insert(detail); + } + + @Override + public List getProductProduceDetailListByLineId(Long lineId) { + return productProduceDetailMapper.selectListByLineId(lineId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineService.java new file mode 100644 index 000000000..3623070c2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineService.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.mes.service.wm.productproduce; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productproduce.vo.MesWmProductProduceLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; + +import java.util.List; + +/** + * MES 生产入库单行 Service 接口 + */ +public interface MesWmProductProduceLineService { + + /** + * 创建生产入库单行(内部使用) + * + * @param line 行数据 + */ + void createProductProduceLine(MesWmProductProduceLineDO line); + + /** + * 更新生产入库单行(内部使用) + * + * @param line 行数据 + */ + void updateProductProduceLine(MesWmProductProduceLineDO line); + + /** + * 根据入库单 ID 获取行列表 + * + * @param produceId 入库单 ID + * @return 行列表 + */ + List getProductProduceLineListByProduceId(Long produceId); + + /** + * 根据报工记录 ID 获取行列表 + * + * @param feedbackId 报工记录 ID + * @return 行列表 + */ + List getProductProduceLineListByFeedbackId(Long feedbackId); + + /** + * 获得生产入库单行分页 + * + * @param pageReqVO 分页查询参数 + * @return 行分页列表 + */ + PageResult getProductProduceLinePage(MesWmProductProduceLinePageReqVO pageReqVO); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineServiceImpl.java new file mode 100644 index 000000000..e88a352f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineServiceImpl.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.service.wm.productproduce; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productproduce.vo.MesWmProductProduceLinePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceLineMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +/** + * MES 生产入库单行 Service 实现类 + */ +@Service +@Validated +public class MesWmProductProduceLineServiceImpl implements MesWmProductProduceLineService { + + @Resource + private MesWmProductProduceLineMapper productProduceLineMapper; + + @Override + public void createProductProduceLine(MesWmProductProduceLineDO line) { + productProduceLineMapper.insert(line); + } + + @Override + public void updateProductProduceLine(MesWmProductProduceLineDO line) { + productProduceLineMapper.updateById(line); + } + + @Override + public List getProductProduceLineListByProduceId(Long produceId) { + return productProduceLineMapper.selectListByProduceId(produceId); + } + + @Override + public List getProductProduceLineListByFeedbackId(Long feedbackId) { + return productProduceLineMapper.selectListByFeedbackId(feedbackId); + } + + @Override + public PageResult getProductProduceLinePage(MesWmProductProduceLinePageReqVO pageReqVO) { + return productProduceLineMapper.selectPage(pageReqVO); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java new file mode 100644 index 000000000..d612272c0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.mes.service.wm.productproduce; + +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO; + +import java.math.BigDecimal; + +/** + * MES 生产入库单 Service 接口 + */ +public interface MesWmProductProduceService { + + /** + * 校验生产入库单是否存在 + * + * @param id 编号 + * @return 生产入库单 + */ + MesWmProductProduceDO validateProductProduceExists(Long id); + + /** + * 完成生产入库单(草稿 → 已完成) + * + * @param id 编号 + */ + void finishProductProduce(Long id); + + /** + * 根据报工记录,自动生成产品产出单(头 + 行 + 明细) + * + * @param feedback 报工记录 + * @param checkFlag 是否需要检验(true=待检验,false=按合格/不合格拆分行) + * @return 生成的产品产出单 + */ + MesWmProductProduceDO generateProductProduce(MesProFeedbackDO feedback, boolean checkFlag); + + /** + * IPQC 检验完成回调:将待检产出拆分为合格/不合格行、生成明细、完成入库 + * + *

调用场景:IPQC 完成时,需要将之前 {@link #generateProductProduce} 生成的 + * 待检产出({@code checkFlag=true})按检验结果拆分行,并执行入库。 + * + * @param feedbackId 报工记录 ID + * @param qualifiedQty 合格品数量 + * @param unqualifiedQty 不合格品数量 + */ + void splitPendingAndFinishProduce(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java new file mode 100644 index 000000000..f4a1f15c2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java @@ -0,0 +1,289 @@ +package cn.iocoder.yudao.module.mes.service.wm.productproduce; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; +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.wm.productproduce.MesWmProductProduceMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductProduceStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 生产入库单 Service 实现类 + */ +@Service +@Validated +public class MesWmProductProduceServiceImpl implements MesWmProductProduceService { + + @Resource + private MesWmProductProduceMapper productProduceMapper; + + @Resource + private MesWmProductProduceLineService productProduceLineService; + @Resource + private MesWmProductProduceDetailService productProduceDetailService; + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesWmBatchService batchService; + @Resource + private MesWmTransactionService wmTransactionService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishProductProduce(Long id) { + // 1.1 校验存在 + 草稿状态 + validateProductProduceExistsAndPrepare(id); + // 1.2 校验至少有一条行 + List lines = productProduceLineService.getProductProduceLineListByProduceId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_PRODUCT_PRODUCE_NO_LINE); + } + + // 2. 创建库存事务 + createTransactionList(id, lines); + + // 3. 更新入库单状态 + productProduceMapper.updateById(new MesWmProductProduceDO() + .setId(id).setStatus(MesWmProductProduceStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(Long produceId, List lines) { + for (MesWmProductProduceLineDO line : lines) { + // 1. 校验每行明细数量之和等于行数量 + List details = productProduceDetailService.getProductProduceDetailListByLineId( + line.getId()); + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmProductProduceDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) { + throw exception(WM_PRODUCT_PRODUCE_DETAIL_QUANTITY_MISMATCH); + } + // 2. 按明细创建库存事务(产品产出到线边库) + for (MesWmProductProduceDetailDO detail : details) { + wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity()) + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setBizType(MesBizTypeConstants.WM_PRODUCT_PRODUCE).setBizId(produceId) + .setBizCode("").setBizLineId(line.getId())); + } + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MesWmProductProduceDO generateProductProduce(MesProFeedbackDO feedback, boolean checkFlag) { + // 0. 查询关联的工单(用于获取 clientId 等信息) + MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(feedback.getWorkOrderId()); + + // 1. 创建产出单头 + MesWmProductProduceDO produce = MesWmProductProduceDO.builder() + .workOrderId(feedback.getWorkOrderId()).feedbackId(feedback.getId()).taskId(feedback.getTaskId()) + .workstationId(feedback.getWorkstationId()).processId(feedback.getProcessId()) + .produceDate(LocalDateTime.now()).status(MesWmProductProduceStatusEnum.PREPARE.getStatus()) + .build(); + productProduceMapper.insert(produce); + + // 2. 获取或生成批次 + MesWmBatchGenerateReqVO batchReqVO = new MesWmBatchGenerateReqVO() + .setItemId(feedback.getItemId()) + .setProduceDate(LocalDate.now().atStartOfDay()) // 截断到当天零点,确保同一天的报工生成相同批次号 + .setExpireDate(feedback.getExpireDate()) + .setWorkOrderId(feedback.getWorkOrderId()) + .setClientId(workOrder != null ? workOrder.getClientId() : null) + .setSalesOrderCode(workOrder != null ? workOrder.getOrderSourceCode() : null) + .setWorkstationId(feedback.getWorkstationId()) + .setLotNumber(feedback.getLotNumber()); + MesWmBatchDO batch = batchService.getOrGenerateBatchCode(batchReqVO); + Long batchId = batch != null ? batch.getId() : null; + String batchCode = batch != null ? batch.getCode() : null; + + // 1.5 获取虚拟线边库 + MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); + + // 3. 根据是否需要检验分支处理 + if (checkFlag) { + // 3.1 需要检验:创建一条行(质量状态=待检验),不生成明细 + MesWmProductProduceLineDO line = buildProduceLine(produce, feedback, batchId, batchCode, + feedback.getFeedbackQuantity(), MesWmQualityStatusEnum.PENDING.getStatus()); + productProduceLineService.createProductProduceLine(line); + // 注意:checkFlag=true 时不生成明细行,等 IPQC 检验完成后由 splitPendingAndFinishProduce 按质量结果拆行+生成明细 + } else { + // 3.2 无需检验:按合格品/不合格品各生成一行 + 明细 + BigDecimal qualifiedQty = ObjectUtil.defaultIfNull(feedback.getQualifiedQuantity(), BigDecimal.ZERO); + BigDecimal unqualifiedQty = ObjectUtil.defaultIfNull(feedback.getUnqualifiedQuantity(), BigDecimal.ZERO); + // 3.2.1 不合格品行 + 明细 + if (unqualifiedQty.compareTo(BigDecimal.ZERO) > 0) { + MesWmProductProduceLineDO unqualifiedLine = buildProduceLine(produce, feedback, batchId, batchCode, + unqualifiedQty, MesWmQualityStatusEnum.FAIL.getStatus()); + productProduceLineService.createProductProduceLine(unqualifiedLine); + MesWmProductProduceDetailDO unqualifiedDetail = buildProduceDetail(produce, feedback, batchId, batchCode, + unqualifiedLine.getId(), unqualifiedQty, + virtualWarehouse.getId(), virtualLocation.getId(), virtualArea.getId()); + productProduceDetailService.createProductProduceDetail(unqualifiedDetail); + } + // 3.2.2 合格品行 + 明细 + if (qualifiedQty.compareTo(BigDecimal.ZERO) > 0) { + MesWmProductProduceLineDO qualifiedLine = buildProduceLine(produce, feedback, batchId, batchCode, + qualifiedQty, MesWmQualityStatusEnum.PASS.getStatus()); + productProduceLineService.createProductProduceLine(qualifiedLine); + MesWmProductProduceDetailDO qualifiedDetail = buildProduceDetail(produce, feedback, batchId, batchCode, + qualifiedLine.getId(), qualifiedQty, + virtualWarehouse.getId(), virtualLocation.getId(), virtualArea.getId()); + productProduceDetailService.createProductProduceDetail(qualifiedDetail); + } + } + return produce; + } + + private MesWmProductProduceLineDO buildProduceLine(MesWmProductProduceDO produce, MesProFeedbackDO feedback, + Long batchId, String batchCode, + BigDecimal quantity, Integer qualityStatus) { + return MesWmProductProduceLineDO.builder() + .produceId(produce.getId()).feedbackId(feedback.getId()) + .itemId(feedback.getItemId()).quantity(quantity) + .batchId(batchId).batchCode(batchCode) + .expireDate(feedback.getExpireDate()).lotNumber(feedback.getLotNumber()) + .qualityStatus(qualityStatus) + .build(); + } + + private MesWmProductProduceDetailDO buildProduceDetail(MesWmProductProduceDO produce, MesProFeedbackDO feedback, + Long batchId, String batchCode, + Long lineId, BigDecimal quantity, + Long warehouseId, Long locationId, Long areaId) { + return MesWmProductProduceDetailDO.builder() + .produceId(produce.getId()).lineId(lineId) + .itemId(feedback.getItemId()).quantity(quantity) + .batchId(batchId).batchCode(batchCode) + .warehouseId(warehouseId).locationId(locationId).areaId(areaId) + .build(); + } + + @Override + public MesWmProductProduceDO validateProductProduceExists(Long id) { + MesWmProductProduceDO produce = productProduceMapper.selectById(id); + if (produce == null) { + throw exception(WM_PRODUCT_PRODUCE_NOT_EXISTS); + } + return produce; + } + + /** + * 校验生产入库单存在且为准备中状态 + */ + private MesWmProductProduceDO validateProductProduceExistsAndPrepare(Long id) { + MesWmProductProduceDO produce = validateProductProduceExists(id); + if (ObjUtil.notEqual(produce.getStatus(), MesWmProductProduceStatusEnum.PREPARE.getStatus())) { + throw exception(WM_PRODUCT_PRODUCE_STATUS_INVALID); + } + return produce; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void splitPendingAndFinishProduce(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty) { + // 1.1 查询产出单 + MesWmProductProduceDO produce = productProduceMapper.selectByFeedbackId(feedbackId); + if (produce == null) { + throw exception(WM_PRODUCT_PRODUCE_NOT_EXISTS); + } + // 1.2 获取虚拟线边库 + MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); + + // 2. 查找待检验行(checkFlag=true 时只有一行 PENDING) + List lines = productProduceLineService.getProductProduceLineListByProduceId(produce.getId()); + MesWmProductProduceLineDO pendingLine = CollUtil.findOne(lines, + l -> ObjUtil.equal(l.getQualityStatus(), MesWmQualityStatusEnum.PENDING.getStatus())); + if (pendingLine == null) { + throw exception(WM_PRODUCT_PRODUCE_LINE_NOT_EXISTS); + } + + // 3A. 情况一:存在不合格品数量,需要拆分行 + if (unqualifiedQty != null && unqualifiedQty.compareTo(BigDecimal.ZERO) > 0) { + // 3A.1 不合格品:新建一行 + 明细 + MesWmProductProduceLineDO unqualifiedLine = MesWmProductProduceLineDO.builder() + .produceId(produce.getId()).feedbackId(feedbackId) + .itemId(pendingLine.getItemId()).quantity(unqualifiedQty) + .batchId(pendingLine.getBatchId()).batchCode(pendingLine.getBatchCode()) + .expireDate(pendingLine.getExpireDate()).lotNumber(pendingLine.getLotNumber()) + .qualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) + .build(); + productProduceLineService.createProductProduceLine(unqualifiedLine); + productProduceDetailService.createProductProduceDetail(MesWmProductProduceDetailDO.builder() + .produceId(produce.getId()).lineId(unqualifiedLine.getId()) + .itemId(pendingLine.getItemId()).quantity(unqualifiedQty) + .batchId(pendingLine.getBatchId()).batchCode(pendingLine.getBatchCode()) + .warehouseId(virtualWarehouse.getId()).locationId(virtualLocation.getId()).areaId(virtualArea.getId()) + .build()); + // 3A.2 合格品:复用原待检行,更新数量和状态 + 明细 + pendingLine.setQuantity(ObjectUtil.defaultIfNull(qualifiedQty, BigDecimal.ZERO)); + pendingLine.setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus()); + productProduceLineService.updateProductProduceLine(pendingLine); + if (qualifiedQty != null && qualifiedQty.compareTo(BigDecimal.ZERO) > 0) { + productProduceDetailService.createProductProduceDetail(MesWmProductProduceDetailDO.builder() + .produceId(produce.getId()).lineId(pendingLine.getId()) + .itemId(pendingLine.getItemId()).quantity(qualifiedQty) + .batchId(pendingLine.getBatchId()).batchCode(pendingLine.getBatchCode()) + .warehouseId(virtualWarehouse.getId()).locationId(virtualLocation.getId()).areaId(virtualArea.getId()) + .build()); + } + } else { + // 3B. 情况二:全部合格,直接更新行状态 + 明细 + pendingLine.setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus()); + productProduceLineService.updateProductProduceLine(pendingLine); + productProduceDetailService.createProductProduceDetail(MesWmProductProduceDetailDO.builder() + .produceId(produce.getId()).lineId(pendingLine.getId()) + .itemId(pendingLine.getItemId()).quantity(pendingLine.getQuantity()) + .batchId(pendingLine.getBatchId()).batchCode(pendingLine.getBatchCode()) + .warehouseId(virtualWarehouse.getId()).locationId(virtualLocation.getId()).areaId(virtualArea.getId()) + .build()); + } + + // 4. 完成产出单(创建库存事务 + 更新状态为已完成) + finishProductProduce(produce.getId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptDetailService.java new file mode 100644 index 000000000..a42dbaeef --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptDetailService.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.service.wm.productreceipt; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.detail.MesWmProductReceiptDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 产品收货单明细 Service 接口 + */ +public interface MesWmProductReceiptDetailService { + + /** + * 创建产品收货单明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductReceiptDetail(@Valid MesWmProductReceiptDetailSaveReqVO createReqVO); + + /** + * 修改产品收货单明细 + * + * @param updateReqVO 修改信息 + */ + void updateProductReceiptDetail(@Valid MesWmProductReceiptDetailSaveReqVO updateReqVO); + + /** + * 删除产品收货单明细 + * + * @param id 编号 + */ + void deleteProductReceiptDetail(Long id); + + /** + * 获得产品收货单明细 + * + * @param id 编号 + * @return 产品收货单明细 + */ + MesWmProductReceiptDetailDO getProductReceiptDetail(Long id); + + /** + * 按收货单编号获得明细列表 + * + * @param receiptId 收货单编号 + * @return 明细列表 + */ + List getProductReceiptDetailListByRecptId(Long receiptId); + + /** + * 按收货单行编号获得明细列表 + * + * @param lineId 行编号 + * @return 明细列表 + */ + List getProductReceiptDetailListByLineId(Long lineId); + + /** + * 按收货单行编号批量删除明细 + * + * @param lineId 行编号 + */ + void deleteProductReceiptDetailByLineId(Long lineId); + + /** + * 按收货单编号批量删除明细 + * + * @param receiptId 收货单编号 + */ + void deleteProductReceiptDetailByRecptId(Long receiptId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptDetailServiceImpl.java new file mode 100644 index 000000000..06c359614 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptDetailServiceImpl.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.mes.service.wm.productreceipt; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.detail.MesWmProductReceiptDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt.MesWmProductReceiptDetailMapper; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 产品收货单明细 Service 实现类 + */ +@Service +@Validated +public class MesWmProductReceiptDetailServiceImpl implements MesWmProductReceiptDetailService { + + @Resource + private MesWmProductReceiptDetailMapper productReceiptDetailMapper; + + @Resource + @Lazy + private MesWmProductReceiptService productReceiptService; + + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + + @Override + public Long createProductReceiptDetail(MesWmProductReceiptDetailSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateProductReceiptDetailSaveData(createReqVO); + + // 2. 新增 + MesWmProductReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmProductReceiptDetailDO.class); + productReceiptDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateProductReceiptDetail(MesWmProductReceiptDetailSaveReqVO updateReqVO) { + // 1.1 校验存在 + MesWmProductReceiptDetailDO detail = validateProductReceiptDetailExists(updateReqVO.getId()); + // 1.2 校验关联数据 + updateReqVO.setReceiptId(detail.getReceiptId()); + validateProductReceiptDetailSaveData(updateReqVO); + + // 2. 更新 + MesWmProductReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductReceiptDetailDO.class); + productReceiptDetailMapper.updateById(updateObj); + } + + @Override + public void deleteProductReceiptDetail(Long id) { + // 校验存在 + MesWmProductReceiptDetailDO detail = validateProductReceiptDetailExists(id); + // 校验父单据存在且为可编辑状态 + productReceiptService.validateProductReceiptEditable(detail.getReceiptId()); + + // 删除 + productReceiptDetailMapper.deleteById(id); + } + + @Override + public MesWmProductReceiptDetailDO getProductReceiptDetail(Long id) { + return productReceiptDetailMapper.selectById(id); + } + + @Override + public List getProductReceiptDetailListByRecptId(Long receiptId) { + return productReceiptDetailMapper.selectListByRecptId(receiptId); + } + + @Override + public List getProductReceiptDetailListByLineId(Long lineId) { + return productReceiptDetailMapper.selectListByLineId(lineId); + } + + @Override + public void deleteProductReceiptDetailByLineId(Long lineId) { + productReceiptDetailMapper.deleteByLineId(lineId); + } + + @Override + public void deleteProductReceiptDetailByRecptId(Long receiptId) { + productReceiptDetailMapper.deleteByRecptId(receiptId); + } + + private MesWmProductReceiptDetailDO validateProductReceiptDetailExists(Long id) { + MesWmProductReceiptDetailDO detail = productReceiptDetailMapper.selectById(id); + if (detail == null) { + throw exception(WM_PRODUCT_RECPT_DETAIL_NOT_EXISTS); + } + return detail; + } + + /** + * 校验明细保存时的关联数据 + */ + private void validateProductReceiptDetailSaveData(MesWmProductReceiptDetailSaveReqVO reqVO) { + // 校验父单据存在且为可编辑状态 + productReceiptService.validateProductReceiptEditable(reqVO.getReceiptId()); + // 校验仓库层级关系 + warehouseAreaService.validateWarehouseAreaExists( + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineService.java new file mode 100644 index 000000000..2cfeebfb7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineService.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.service.wm.productreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line.MesWmProductReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line.MesWmProductReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 产品收货单行 Service 接口 + */ +public interface MesWmProductReceiptLineService { + + /** + * 创建产品收货单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductReceiptLine(@Valid MesWmProductReceiptLineSaveReqVO createReqVO); + + /** + * 修改产品收货单行 + * + * @param updateReqVO 修改信息 + */ + void updateProductReceiptLine(@Valid MesWmProductReceiptLineSaveReqVO updateReqVO); + + /** + * 删除产品收货单行(级联删除明细) + * + * @param id 编号 + */ + void deleteProductReceiptLine(Long id); + + /** + * 获得产品收货单行 + * + * @param id 编号 + * @return 产品收货单行 + */ + MesWmProductReceiptLineDO getProductReceiptLine(Long id); + + /** + * 获得产品收货单行分页 + * + * @param pageReqVO 分页参数 + * @return 产品收货单行分页 + */ + PageResult getProductReceiptLinePage(MesWmProductReceiptLinePageReqVO pageReqVO); + + /** + * 按收货单编号获得行列表 + * + * @param receiptId 收货单编号 + * @return 行列表 + */ + List getProductReceiptLineListByRecptId(Long receiptId); + + /** + * 按收货单编号批量删除行 + * + * @param receiptId 收货单编号 + */ + void deleteProductReceiptLineByRecptId(Long receiptId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineServiceImpl.java new file mode 100644 index 000000000..4582437d9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineServiceImpl.java @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.mes.service.wm.productreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line.MesWmProductReceiptLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.line.MesWmProductReceiptLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt.MesWmProductReceiptLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_RECPT_LINE_NOT_EXISTS; + +/** + * MES 产品收货单行 Service 实现类 + */ +@Service +@Validated +public class MesWmProductReceiptLineServiceImpl implements MesWmProductReceiptLineService { + + @Resource + private MesWmProductReceiptLineMapper productReceiptLineMapper; + + @Resource + @Lazy + private MesWmProductReceiptService productReceiptService; + + @Resource + private MesWmProductReceiptDetailService productReceiptDetailService; + + @Resource + private MesMdItemService itemService; + + @Override + public Long createProductReceiptLine(MesWmProductReceiptLineSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateProductReceiptLineSaveData(createReqVO); + + // 2. 新增 + MesWmProductReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmProductReceiptLineDO.class); + productReceiptLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateProductReceiptLine(MesWmProductReceiptLineSaveReqVO updateReqVO) { + // 1.1 校验存在 + MesWmProductReceiptLineDO line = validateProductReceiptLineExists(updateReqVO.getId()); + // 1.2 校验关联数据 + updateReqVO.setReceiptId(line.getReceiptId()); + validateProductReceiptLineSaveData(updateReqVO); + + // 2. 更新 + MesWmProductReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductReceiptLineDO.class); + productReceiptLineMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteProductReceiptLine(Long id) { + // 校验存在 + MesWmProductReceiptLineDO line = validateProductReceiptLineExists(id); + // 校验父单据存在且为可编辑状态 + productReceiptService.validateProductReceiptEditable(line.getReceiptId()); + + // 级联删除明细 + productReceiptDetailService.deleteProductReceiptDetailByLineId(id); + // 删除 + productReceiptLineMapper.deleteById(id); + } + + @Override + public MesWmProductReceiptLineDO getProductReceiptLine(Long id) { + return productReceiptLineMapper.selectById(id); + } + + @Override + public PageResult getProductReceiptLinePage(MesWmProductReceiptLinePageReqVO pageReqVO) { + return productReceiptLineMapper.selectPage(pageReqVO); + } + + @Override + public List getProductReceiptLineListByRecptId(Long receiptId) { + return productReceiptLineMapper.selectListByRecptId(receiptId); + } + + @Override + public void deleteProductReceiptLineByRecptId(Long receiptId) { + productReceiptLineMapper.deleteByRecptId(receiptId); + } + + private MesWmProductReceiptLineDO validateProductReceiptLineExists(Long id) { + MesWmProductReceiptLineDO line = productReceiptLineMapper.selectById(id); + if (line == null) { + throw exception(WM_PRODUCT_RECPT_LINE_NOT_EXISTS); + } + return line; + } + + /** + * 校验行保存时的关联数据 + */ + private void validateProductReceiptLineSaveData(MesWmProductReceiptLineSaveReqVO reqVO) { + // 校验父单据存在且为可编辑状态 + productReceiptService.validateProductReceiptEditable(reqVO.getReceiptId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptService.java new file mode 100644 index 000000000..e2459b597 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptService.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.mes.service.wm.productreceipt; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDO; +import jakarta.validation.Valid; + +/** + * MES 产品收货单 Service 接口 + */ +public interface MesWmProductReceiptService { + + /** + * 创建产品收货单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductReceipt(@Valid MesWmProductReceiptSaveReqVO createReqVO); + + /** + * 修改产品收货单 + * + * @param updateReqVO 修改信息 + */ + void updateProductReceipt(@Valid MesWmProductReceiptSaveReqVO updateReqVO); + + /** + * 删除产品收货单(级联删除行+明细) + * + * @param id 编号 + */ + void deleteProductReceipt(Long id); + + /** + * 获得产品收货单 + * + * @param id 编号 + * @return 产品收货单 + */ + MesWmProductReceiptDO getProductReceipt(Long id); + + /** + * 获得产品收货单分页 + * + * @param pageReqVO 分页参数 + * @return 产品收货单分页 + */ + PageResult getProductReceiptPage(MesWmProductReceiptPageReqVO pageReqVO); + + /** + * 提交产品收货单(草稿 → 待上架) + * + * @param id 编号 + */ + void submitProductReceipt(Long id); + + /** + * 执行上架(待上架 → 待入库) + * + * @param id 编号 + */ + void stockProductReceipt(Long id); + + /** + * 执行入库(待入库 → 已完成),更新库存台账 + * + * @param id 编号 + */ + void finishProductReceipt(Long id); + + /** + * 取消产品收货单(任意非已完成/已取消状态 → 已取消) + * + * @param id 编号 + */ + void cancelProductReceipt(Long id); + + /** + * 校验产品收货单存在且处于可编辑状态(草稿或待上架) + * + * @param id 编号 + * @return 产品收货单 + */ + MesWmProductReceiptDO validateProductReceiptEditable(Long id); + + /** + * 校验产品收货单明细数量(每行明细数量之和是否等于行收货数量) + * + * @param id 编号 + * @return 是否匹配 + */ + Boolean checkProductReceiptQuantity(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java new file mode 100644 index 000000000..7e9689cf9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java @@ -0,0 +1,283 @@ +package cn.iocoder.yudao.module.mes.service.wm.productreceipt; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo.MesWmProductReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productreceipt.MesWmProductReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productreceipt.MesWmProductReceiptMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductReceiptStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 产品收货单 Service 实现类 + */ +@Service +@Validated +public class MesWmProductReceiptServiceImpl implements MesWmProductReceiptService { + + @Resource + private MesWmProductReceiptMapper productReceiptMapper; + + @Resource + private MesWmProductReceiptLineService productReceiptLineService; + + @Resource + private MesWmProductReceiptDetailService productReceiptDetailService; + + @Resource + private MesWmTransactionService wmTransactionService; + + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + + @Override + public Long createProductReceipt(MesWmProductReceiptSaveReqVO createReqVO) { + // 1. 校验关联数据 + MesProWorkOrderDO workOrder = validateProductReceiptSaveData(createReqVO); + + // 2. 插入 + MesWmProductReceiptDO receipt = BeanUtils.toBean(createReqVO, MesWmProductReceiptDO.class); + if (workOrder != null) { + receipt.setItemId(workOrder.getProductId()); + } + receipt.setStatus(MesWmProductReceiptStatusEnum.PREPARE.getStatus()); + productReceiptMapper.insert(receipt); + return receipt.getId(); + } + + @Override + public void updateProductReceipt(MesWmProductReceiptSaveReqVO updateReqVO) { + // 1.1 校验存在 + 草稿状态 + validateProductReceiptExistsAndDraft(updateReqVO.getId()); + // 1.2 校验关联数据 + MesProWorkOrderDO workOrder = validateProductReceiptSaveData(updateReqVO); + + // 2. 更新 + MesWmProductReceiptDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductReceiptDO.class); + if (workOrder != null) { + updateObj.setItemId(workOrder.getProductId()); + } + productReceiptMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteProductReceipt(Long id) { + // 校验存在 + 草稿状态 + validateProductReceiptExistsAndDraft(id); + + // 级联删除明细和行 + productReceiptDetailService.deleteProductReceiptDetailByRecptId(id); + productReceiptLineService.deleteProductReceiptLineByRecptId(id); + // 删除 + productReceiptMapper.deleteById(id); + } + + @Override + public MesWmProductReceiptDO getProductReceipt(Long id) { + return productReceiptMapper.selectById(id); + } + + @Override + public PageResult getProductReceiptPage(MesWmProductReceiptPageReqVO pageReqVO) { + return productReceiptMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitProductReceipt(Long id) { + // 校验存在 + 草稿状态 + validateProductReceiptExistsAndDraft(id); + // 校验至少有一条行 + List lines = productReceiptLineService.getProductReceiptLineListByRecptId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_PRODUCT_RECPT_NO_LINE); + } + + // 提交(草稿 → 待上架) + productReceiptMapper.updateById(new MesWmProductReceiptDO() + .setId(id).setStatus(MesWmProductReceiptStatusEnum.APPROVING.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockProductReceipt(Long id) { + // 校验存在 + MesWmProductReceiptDO receipt = validateProductReceiptExists(id); + if (ObjUtil.notEqual(MesWmProductReceiptStatusEnum.APPROVING.getStatus(), receipt.getStatus())) { + throw exception(WM_PRODUCT_RECPT_STATUS_ERROR); + } + + // 执行上架(待上架 → 待入库) + productReceiptMapper.updateById(new MesWmProductReceiptDO() + .setId(id).setStatus(MesWmProductReceiptStatusEnum.APPROVED.getStatus())); + } + + @Override + public Boolean checkProductReceiptQuantity(Long id) { + List lines = productReceiptLineService.getProductReceiptLineListByRecptId(id); + for (MesWmProductReceiptLineDO line : lines) { + List details = productReceiptDetailService.getProductReceiptDetailListByLineId(line.getId()); + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmProductReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) { + return false; + } + } + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishProductReceipt(Long id) { + // 校验存在 + MesWmProductReceiptDO receipt = validateProductReceiptExists(id); + if (ObjUtil.notEqual(MesWmProductReceiptStatusEnum.APPROVED.getStatus(), receipt.getStatus())) { + throw exception(WM_PRODUCT_RECPT_STATUS_ERROR); + } + // 校验明细非空 + List details = productReceiptDetailService.getProductReceiptDetailListByRecptId(id); + if (CollUtil.isEmpty(details)) { + throw exception(WM_PRODUCT_RECPT_NO_DETAIL); + } + + // 创建库存事务 + createTransactionList(receipt, details); + + // 更新收货单状态 + productReceiptMapper.updateById(new MesWmProductReceiptDO() + .setId(id).setStatus(MesWmProductReceiptStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmProductReceiptDO receipt, List details) { + // 1. 查询虚拟线边库 + MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); + + // 2. 遍历明细,每条明细产生 OUT(虚拟线边库扣减)+ IN(实际仓库增加) + for (MesWmProductReceiptDetailDO detail : details) { + // 2.1 先从虚拟线边库出库(库存减少) + Long outTransactionId = wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity().negate()) // 库存减少 + .setBatchId(detail.getBatchId()) + .setWarehouseId(virtualWarehouse.getId()).setLocationId(virtualLocation.getId()).setAreaId(virtualArea.getId()) + .setCheckFlag(false) // 线边库允许负库存 + .setBizType(MesBizTypeConstants.WM_PRODUCT_RECPT).setBizId(receipt.getId()) + .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId())); + // 2.2 再入实际仓库(库存增加) + wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity()) // 库存增加 + .setBatchId(detail.getBatchId()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setBizType(MesBizTypeConstants.WM_PRODUCT_RECPT).setBizId(receipt.getId()) + .setBizCode(receipt.getCode()).setBizLineId(detail.getLineId()) + .setRelatedTransactionId(outTransactionId)); // 关联出库事务 + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelProductReceipt(Long id) { + // 校验存在 + MesWmProductReceiptDO receipt = validateProductReceiptExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(receipt.getStatus(), + MesWmProductReceiptStatusEnum.FINISHED.getStatus(), + MesWmProductReceiptStatusEnum.CANCELED.getStatus())) { + throw exception(WM_PRODUCT_RECPT_CANCEL_NOT_ALLOWED); + } + + // 取消 + productReceiptMapper.updateById(new MesWmProductReceiptDO() + .setId(id).setStatus(MesWmProductReceiptStatusEnum.CANCELED.getStatus())); + } + + @Override + public MesWmProductReceiptDO validateProductReceiptEditable(Long id) { + MesWmProductReceiptDO receipt = validateProductReceiptExists(id); + if (ObjUtil.notEqual(receipt.getStatus(), MesWmProductReceiptStatusEnum.PREPARE.getStatus()) + && ObjUtil.notEqual(receipt.getStatus(), MesWmProductReceiptStatusEnum.APPROVING.getStatus())) { + throw exception(WM_PRODUCT_RECPT_STATUS_NOT_PREPARE); + } + return receipt; + } + + private MesWmProductReceiptDO validateProductReceiptExists(Long id) { + MesWmProductReceiptDO receipt = productReceiptMapper.selectById(id); + if (receipt == null) { + throw exception(WM_PRODUCT_RECPT_NOT_EXISTS); + } + return receipt; + } + + /** + * 校验产品收货单存在且为草稿状态 + */ + private MesWmProductReceiptDO validateProductReceiptExistsAndDraft(Long id) { + MesWmProductReceiptDO receipt = validateProductReceiptExists(id); + if (ObjUtil.notEqual(MesWmProductReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())) { + throw exception(WM_PRODUCT_RECPT_STATUS_NOT_PREPARE); + } + return receipt; + } + /** + * 校验保存时的关联数据 + * + * @return 工单对象(可能为 null) + */ + private MesProWorkOrderDO validateProductReceiptSaveData(MesWmProductReceiptSaveReqVO reqVO) { + // 校验编码唯一 + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验工单存在 + return reqVO.getWorkOrderId() != null ? + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()) : null; + } + + private void validateCodeUnique(Long id, String code) { + MesWmProductReceiptDO receipt = productReceiptMapper.selectByCode(code); + if (receipt == null) { + return; + } + if (ObjUtil.notEqual(id, receipt.getId())) { + throw exception(WM_PRODUCT_RECPT_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailService.java new file mode 100644 index 000000000..23d0997e5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailService.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.service.wm.productsales; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail.MesWmProductSalesDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 销售出库明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmProductSalesDetailService { + + /** + * 创建销售出库明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductSalesDetail(@Valid MesWmProductSalesDetailSaveReqVO createReqVO); + + /** + * 修改销售出库明细 + * + * @param updateReqVO 修改信息 + */ + void updateProductSalesDetail(@Valid MesWmProductSalesDetailSaveReqVO updateReqVO); + + /** + * 删除销售出库明细 + * + * @param id 编号 + */ + void deleteProductSalesDetail(Long id); + + /** + * 获得销售出库明细 + * + * @param id 编号 + * @return 销售出库明细 + */ + MesWmProductSalesDetailDO getProductSalesDetail(Long id); + + /** + * 按出库单编号获得明细列表 + * + * @param salesId 出库单编号 + * @return 明细列表 + */ + List getProductSalesDetailListBySalesId(Long salesId); + + /** + * 按出库单行编号获得明细列表 + * + * @param lineId 行编号 + * @return 明细列表 + */ + List getProductSalesDetailListByLineId(Long lineId); + + /** + * 按出库单行编号批量删除明细 + * + * @param lineId 行编号 + */ + void deleteProductSalesDetailByLineId(Long lineId); + + /** + * 按出库单编号批量删除明细 + * + * @param salesId 出库单编号 + */ + void deleteProductSalesDetailBySalesId(Long salesId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java new file mode 100644 index 000000000..3f2657bc7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.mes.service.wm.productsales; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail.MesWmProductSalesDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesDetailMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 销售出库明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmProductSalesDetailServiceImpl implements MesWmProductSalesDetailService { + + @Resource + private MesWmProductSalesDetailMapper productSalesDetailMapper; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + + @Override + public Long createProductSalesDetail(MesWmProductSalesDetailSaveReqVO createReqVO) { + // 校验物料存在 + itemService.validateItemExists(createReqVO.getItemId()); + // 校验库区关系 + warehouseAreaService.validateWarehouseAreaExists( + createReqVO.getWarehouseId(), createReqVO.getLocationId(), createReqVO.getAreaId()); + + // 插入 + MesWmProductSalesDetailDO detail = BeanUtils.toBean(createReqVO, MesWmProductSalesDetailDO.class); + productSalesDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateProductSalesDetail(MesWmProductSalesDetailSaveReqVO updateReqVO) { + // 校验存在 + validateProductSalesDetailExists(updateReqVO.getId()); + // 校验物料存在 + itemService.validateItemExists(updateReqVO.getItemId()); + // 校验库区关系 + warehouseAreaService.validateWarehouseAreaExists( + updateReqVO.getWarehouseId(), updateReqVO.getLocationId(), updateReqVO.getAreaId()); + + // 更新 + MesWmProductSalesDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesDetailDO.class); + productSalesDetailMapper.updateById(updateObj); + } + + @Override + public void deleteProductSalesDetail(Long id) { + // 校验存在 + validateProductSalesDetailExists(id); + // 删除 + productSalesDetailMapper.deleteById(id); + } + + @Override + public MesWmProductSalesDetailDO getProductSalesDetail(Long id) { + return productSalesDetailMapper.selectById(id); + } + + @Override + public List getProductSalesDetailListBySalesId(Long salesId) { + return productSalesDetailMapper.selectListBySalesId(salesId); + } + + @Override + public List getProductSalesDetailListByLineId(Long lineId) { + return productSalesDetailMapper.selectListByLineId(lineId); + } + + @Override + public void deleteProductSalesDetailByLineId(Long lineId) { + productSalesDetailMapper.deleteByLineId(lineId); + } + + @Override + public void deleteProductSalesDetailBySalesId(Long salesId) { + productSalesDetailMapper.deleteBySalesId(salesId); + } + + private MesWmProductSalesDetailDO validateProductSalesDetailExists(Long id) { + MesWmProductSalesDetailDO detail = productSalesDetailMapper.selectById(id); + if (detail == null) { + throw exception(WM_PRODUCT_SALES_DETAIL_NOT_EXISTS); + } + return detail; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineService.java new file mode 100644 index 000000000..f1327bc7d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineService.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.mes.service.wm.productsales; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 销售出库单行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmProductSalesLineService { + + /** + * 创建销售出库单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductSalesLine(@Valid MesWmProductSalesLineSaveReqVO createReqVO); + + /** + * 修改销售出库单行 + * + * @param updateReqVO 修改信息 + */ + void updateProductSalesLine(@Valid MesWmProductSalesLineSaveReqVO updateReqVO); + + /** + * 删除销售出库单行(级联删除明细) + * + * @param id 编号 + */ + void deleteProductSalesLine(Long id); + + /** + * 获得销售出库单行 + * + * @param id 编号 + * @return 销售出库单行 + */ + MesWmProductSalesLineDO getProductSalesLine(Long id); + + /** + * 按出库单编号获得行列表 + * + * @param salesId 出库单编号 + * @return 行列表 + */ + List getProductSalesLineListBySalesId(Long salesId); + + /** + * 按出库单编号批量删除行 + * + * @param salesId 出库单编号 + */ + void deleteProductSalesLineBySalesId(Long salesId); + + /** + * 获得销售出库单行分页 + * + * @param pageReqVO 分页查询 + * @return 销售出库单行分页 + */ + PageResult getProductSalesLinePage(MesWmProductSalesLinePageReqVO pageReqVO); + + /** + * OQC 检验完成后,更新销售出库单行的 OQC 质检状态 + * + * @param id 行 ID + * @param oqcId 质检单 ID + * @param checkResult 检验结果 + */ + void updateProductSalesLineWhenOqcFinish(Long id, Long oqcId, Integer checkResult); + + /** + * 批量更新行的质量状态 + * + * @param ids 行 ID 列表 + * @param qualityStatus 质量状态 + */ + void updateProductSalesLineQualityStatus(List ids, Integer qualityStatus); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java new file mode 100644 index 000000000..c9cff119b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java @@ -0,0 +1,187 @@ +package cn.iocoder.yudao.module.mes.service.wm.productsales; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_SALES_LINE_NOT_EXISTS; + +/** + * MES 销售出库单行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineService { + + @Resource + private MesWmProductSalesLineMapper productSalesLineMapper; + @Resource + private MesWmProductSalesDetailService productSalesDetailService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmBatchService batchService; + @Resource + @Lazy + private MesWmProductSalesService productSalesService; + + @Override + public Long createProductSalesLine(MesWmProductSalesLineSaveReqVO createReqVO) { + // 校验物料存在 + itemService.validateItemExists(createReqVO.getItemId()); + // 根据 batchCode 解析 batchId + fillBatchId(createReqVO); + + // 新增 + MesWmProductSalesLineDO line = BeanUtils.toBean(createReqVO, MesWmProductSalesLineDO.class); + productSalesLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateProductSalesLine(MesWmProductSalesLineSaveReqVO updateReqVO) { + // 校验存在 + validateProductSalesLineExists(updateReqVO.getId()); + // 校验物料存在 + itemService.validateItemExists(updateReqVO.getItemId()); + // 根据 batchCode 解析 batchId + fillBatchId(updateReqVO); + + // 更新 + MesWmProductSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesLineDO.class); + productSalesLineMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteProductSalesLine(Long id) { + // 校验存在 + validateProductSalesLineExists(id); + + // 级联删除明细 + productSalesDetailService.deleteProductSalesDetailByLineId(id); + // 删除 + productSalesLineMapper.deleteById(id); + } + + @Override + public MesWmProductSalesLineDO getProductSalesLine(Long id) { + return productSalesLineMapper.selectById(id); + } + + @Override + public List getProductSalesLineListBySalesId(Long salesId) { + return productSalesLineMapper.selectListBySalesId(salesId); + } + + @Override + public void deleteProductSalesLineBySalesId(Long salesId) { + productSalesLineMapper.deleteBySalesId(salesId); + } + + @Override + public cn.iocoder.yudao.framework.common.pojo.PageResult getProductSalesLinePage( + MesWmProductSalesLinePageReqVO pageReqVO) { + // 如果传了 clientId,先查出该客户的所有出库单 ID,设置到 salesIds + if (pageReqVO.getSalesId() == null && pageReqVO.getClientId() != null) { + List salesList = productSalesService.getProductSalesListByClientId(pageReqVO.getClientId()); + if (CollUtil.isEmpty(salesList)) { + return cn.iocoder.yudao.framework.common.pojo.PageResult.empty(); + } + pageReqVO.setSalesIds(convertList(salesList, MesWmProductSalesDO::getId)); + } + // 查询分页 + return productSalesLineMapper.selectPage(pageReqVO); + } + + private MesWmProductSalesLineDO validateProductSalesLineExists(Long id) { + MesWmProductSalesLineDO line = productSalesLineMapper.selectById(id); + if (line == null) { + throw exception(WM_PRODUCT_SALES_LINE_NOT_EXISTS); + } + return line; + } + + /** + * 根据 batchCode 解析 batchId + */ + private void fillBatchId(MesWmProductSalesLineSaveReqVO reqVO) { + if (StrUtil.isBlank(reqVO.getBatchCode())) { + reqVO.setBatchId(null); + return; + } + MesWmBatchDO batch = batchService.getBatchByCode(reqVO.getBatchCode()); + reqVO.setBatchId(batch != null ? batch.getId() : null); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateProductSalesLineWhenOqcFinish(Long id, Long oqcId, Integer checkResult) { + // 1. 更新行的 oqcId + qualityStatus + Integer qualityStatus = Objects.equals(checkResult, MesQcCheckResultEnum.PASS.getType()) + ? MesWmQualityStatusEnum.PASS.getStatus() : MesWmQualityStatusEnum.FAIL.getStatus(); + productSalesLineMapper.updateById(new MesWmProductSalesLineDO() + .setId(id).setOqcId(oqcId).setQualityStatus(qualityStatus)); + + // 2. 检查同一出库单下所有需要 OQC 检验的行 + MesWmProductSalesLineDO currentLine = productSalesLineMapper.selectById(id); + if (currentLine == null || currentLine.getSalesId() == null) { + return; + } + Long salesId = currentLine.getSalesId(); + List allLines = productSalesLineMapper.selectListBySalesId(salesId); + + // 2.1 检查是否有不合格行 → 取消出库单 + boolean hasNg = CollectionUtils.anyMatch(allLines, + line -> Boolean.TRUE.equals(line.getOqcCheckFlag()) + && Objects.equals(line.getQualityStatus(), MesWmQualityStatusEnum.FAIL.getStatus())); + if (hasNg) { + log.info("[updateProductSalesLineWhenOqcFinish][销售出库单({}) 存在质检不合格行,取消出库单]", salesId); + productSalesService.cancelProductSales(salesId); + return; + } + + // 2.2 检查是否所有 OQC 行都已完成,自动流转 CONFIRMED → APPROVING + boolean hasUnchecked = CollectionUtils.anyMatch(allLines, + line -> Boolean.TRUE.equals(line.getOqcCheckFlag()) && line.getOqcId() == null); + if (!hasUnchecked) { + log.info("[updateProductSalesLineWhenOqcFinish][销售出库单({}) 所有 OQC 行检验完成,流转到待拣货]", salesId); + productSalesService.confirmProductSales(salesId); + } + } + + @Override + public void updateProductSalesLineQualityStatus(List ids, Integer qualityStatus) { + if (CollUtil.isEmpty(ids)) { + return; + } + productSalesLineMapper.updateQualityStatusByIds(ids, qualityStatus); + } + +} + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesService.java new file mode 100644 index 000000000..64a3d1ea5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesService.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.mes.service.wm.productsales; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 销售出库单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmProductSalesService { + + /** + * 创建销售出库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductSales(@Valid MesWmProductSalesSaveReqVO createReqVO); + + /** + * 修改销售出库单 + * + * @param updateReqVO 修改信息 + */ + void updateProductSales(@Valid MesWmProductSalesSaveReqVO updateReqVO); + + /** + * 删除销售出库单(级联删除行+明细) + * + * @param id 编号 + */ + void deleteProductSales(Long id); + + /** + * 获得销售出库单 + * + * @param id 编号 + * @return 销售出库单 + */ + MesWmProductSalesDO getProductSales(Long id); + + /** + * 获得销售出库单分页 + * + * @param pageReqVO 分页参数 + * @return 销售出库单分页 + */ + PageResult getProductSalesPage(MesWmProductSalesPageReqVO pageReqVO); + + /** + * 提交销售出库单 + *

    + *
  • 有 OQC 检验行:草稿 → 待检测
  • + *
  • 无 OQC 检验行:草稿 → 待拣货
  • + *
+ * + * @param id 编号 + */ + void submitProductSales(Long id); + + /** + * 校验销售出库单数量是否匹配 + * + * @param id 编号 + * @return 是否匹配 + */ + boolean checkProductSalesQuantity(Long id); + + /** + * 执行拣货(待拣货 → 待填写运单) + * + * @param id 编号 + */ + void stockProductSales(Long id); + + /** + * 填写运单(待填写运单 → 待执行出库) + * + * @param reqVO 运单信息 + */ + void shippingProductSales(@Valid MesWmProductSalesShippingReqVO reqVO); + + /** + * 执行出库(待出库 → 已完成),扣减库存 + * + * @param id 编号 + */ + void finishProductSales(Long id); + + /** + * 取消销售出库单(任意非已完成/已取消状态 → 已取消) + * + * @param id 编号 + */ + void cancelProductSales(Long id); + + /** + * OQC 检验完成后,自动流转(待检测 → 待拣货) + * + * @param id 编号 + */ + void confirmProductSales(Long id); + + /** + * 按客户编号获得销售出库单列表 + * + * @param clientId 客户编号 + * @return 出库单列表 + */ + List getProductSalesListByClientId(Long clientId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java new file mode 100644 index 000000000..e92a46ef1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java @@ -0,0 +1,296 @@ +package cn.iocoder.yudao.module.mes.service.wm.productsales; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 销售出库单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { + + @Resource + private MesWmProductSalesMapper productSalesMapper; + + @Resource + private MesWmProductSalesLineService productSalesLineService; + + @Resource + private MesWmProductSalesDetailService productSalesDetailService; + + @Resource + private MesMdClientService clientService; + + @Resource + private MesWmTransactionService wmTransactionService; + + @Override + public Long createProductSales(MesWmProductSalesSaveReqVO createReqVO) { + // 校验数据 + validateProductSalesSaveData(null, createReqVO); + + // 插入 + MesWmProductSalesDO sales = BeanUtils.toBean(createReqVO, MesWmProductSalesDO.class); + sales.setStatus(MesWmProductSalesStatusEnum.PREPARE.getStatus()); + productSalesMapper.insert(sales); + return sales.getId(); + } + + @Override + public void updateProductSales(MesWmProductSalesSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateProductSalesExistsAndDraft(updateReqVO.getId()); + // 校验数据 + validateProductSalesSaveData(updateReqVO.getId(), updateReqVO); + + // 更新 + MesWmProductSalesDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesDO.class); + productSalesMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteProductSales(Long id) { + // 校验存在 + 草稿状态 + validateProductSalesExistsAndDraft(id); + + // 级联删除明细和行 + productSalesDetailService.deleteProductSalesDetailBySalesId(id); + productSalesLineService.deleteProductSalesLineBySalesId(id); + // 删除 + productSalesMapper.deleteById(id); + } + + @Override + public MesWmProductSalesDO getProductSales(Long id) { + return productSalesMapper.selectById(id); + } + + @Override + public PageResult getProductSalesPage(MesWmProductSalesPageReqVO pageReqVO) { + return productSalesMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitProductSales(Long id) { + // 校验存在 + 草稿状态 + validateProductSalesExistsAndDraft(id); + // 校验至少有一条行 + List lines = productSalesLineService.getProductSalesLineListBySalesId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_PRODUCT_SALES_LINES_EMPTY); + } + // 校验每行出库数量 > 0 + for (MesWmProductSalesLineDO line : lines) { + if (line.getQuantity() == null || BigDecimal.ZERO.compareTo(line.getQuantity()) >= 0) { + throw exception(WM_PRODUCT_SALES_LINE_QUANTITY_INVALID); + } + } + + // 检查所有行的 oqcCheckFlag:如果有需要 OQC 检验的行,进入待检测状态 + boolean needOqc = CollectionUtils.anyMatch(lines, + line -> Boolean.TRUE.equals(line.getOqcCheckFlag())); + if (needOqc) { + // 批量初始化 OQC 行的质量状态为"待检验" + List oqcLineIds = convertList( + CollectionUtils.filterList(lines, line -> Boolean.TRUE.equals(line.getOqcCheckFlag())), + MesWmProductSalesLineDO::getId); + productSalesLineService.updateProductSalesLineQualityStatus(oqcLineIds, MesWmQualityStatusEnum.PENDING.getStatus()); + // 需要检验,进入待检测 + productSalesMapper.updateById(new MesWmProductSalesDO() + .setId(id).setStatus(MesWmProductSalesStatusEnum.CONFIRMED.getStatus())); + return; + } + // 不需要检验,直接进入待拣货 + productSalesMapper.updateById(new MesWmProductSalesDO() + .setId(id).setStatus(MesWmProductSalesStatusEnum.APPROVING.getStatus())); + } + + @Override + public boolean checkProductSalesQuantity(Long id) { + // 校验每行明细数量之和是否等于行出库数量 + List lines = productSalesLineService.getProductSalesLineListBySalesId(id); + for (MesWmProductSalesLineDO line : lines) { + List details = productSalesDetailService.getProductSalesDetailListByLineId(line.getId()); + if (CollUtil.isEmpty(details)) { + return false; + } + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmProductSalesDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) { + return false; + } + } + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockProductSales(Long id) { + // 校验存在 + MesWmProductSalesDO sales = validateProductSalesExists(id); + if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.APPROVING.getStatus(), sales.getStatus())) { + throw exception(WM_PRODUCT_SALES_CANNOT_PICK); + } + // 校验每行至少有拣货明细 + List lines = productSalesLineService.getProductSalesLineListBySalesId(id); + for (MesWmProductSalesLineDO line : lines) { + List details = productSalesDetailService.getProductSalesDetailListByLineId(line.getId()); + if (CollUtil.isEmpty(details)) { + throw exception(WM_PRODUCT_SALES_DETAILS_EMPTY); + } + } + + // 执行拣货(待拣货 → 待填写运单) + productSalesMapper.updateById(new MesWmProductSalesDO() + .setId(id).setStatus(MesWmProductSalesStatusEnum.SHIPPING.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void shippingProductSales(MesWmProductSalesShippingReqVO reqVO) { + // 校验存在 + MesWmProductSalesDO sales = validateProductSalesExists(reqVO.getId()); + if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.SHIPPING.getStatus(), sales.getStatus())) { + throw exception(WM_PRODUCT_SALES_CANNOT_SHIPPING); + } + + // 填写运单(待填写运单 → 待执行出库) + productSalesMapper.updateById(new MesWmProductSalesDO() + .setId(reqVO.getId()) + .setCarrier(reqVO.getCarrier()) + .setShippingNumber(reqVO.getShippingNumber()) + .setStatus(MesWmProductSalesStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishProductSales(Long id) { + // 1. 校验存在 + MesWmProductSalesDO sales = validateProductSalesExists(id); + if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.APPROVED.getStatus(), sales.getStatus())) { + throw exception(WM_PRODUCT_SALES_CANNOT_FINISH); + } + + // 2. 遍历所有明细,创建库存事务(扣减库存 + 记录流水) + createTransactionList(sales); + + // 3. 更新出库单状态 + productSalesMapper.updateById(new MesWmProductSalesDO() + .setId(id).setStatus(MesWmProductSalesStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmProductSalesDO sales) { + List details = productSalesDetailService.getProductSalesDetailListBySalesId(sales.getId()); + wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity().negate()) // 出库数量为负数 + .setBatchId(detail.getBatchId()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setBizType(MesBizTypeConstants.WM_PRODUCT_SALES).setBizId(sales.getId()) + .setBizCode(sales.getCode()).setBizLineId(detail.getLineId()))); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelProductSales(Long id) { + // 校验存在 + MesWmProductSalesDO sales = validateProductSalesExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(sales.getStatus(), + MesWmProductSalesStatusEnum.FINISHED.getStatus(), + MesWmProductSalesStatusEnum.CANCELED.getStatus())) { + throw exception(WM_PRODUCT_SALES_CANNOT_CANCEL); + } + // 取消 + productSalesMapper.updateById(new MesWmProductSalesDO() + .setId(id).setStatus(MesWmProductSalesStatusEnum.CANCELED.getStatus())); + } + + @Override + public void confirmProductSales(Long id) { + // 校验存在 + 待检测状态 + MesWmProductSalesDO sales = validateProductSalesExists(id); + if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.CONFIRMED.getStatus(), sales.getStatus())) { + throw exception(WM_PRODUCT_SALES_CANNOT_CONFIRM); + } + // OQC 检验完成,流转到待拣货 + productSalesMapper.updateById(new MesWmProductSalesDO() + .setId(id).setStatus(MesWmProductSalesStatusEnum.APPROVING.getStatus())); + } + + @Override + public List getProductSalesListByClientId(Long clientId) { + return productSalesMapper.selectListByClientId(clientId); + } + + private void validateProductSalesSaveData(Long id, MesWmProductSalesSaveReqVO reqVO) { + // 校验编码唯一 + validateCodeUnique(id, reqVO.getCode()); + // 校验客户存在 + clientService.validateClientExists(reqVO.getClientId()); + } + + private MesWmProductSalesDO validateProductSalesExists(Long id) { + MesWmProductSalesDO sales = productSalesMapper.selectById(id); + if (sales == null) { + throw exception(WM_PRODUCT_SALES_NOT_EXISTS); + } + return sales; + } + + /** + * 校验销售出库单存在且为草稿状态 + */ + private MesWmProductSalesDO validateProductSalesExistsAndDraft(Long id) { + MesWmProductSalesDO sales = validateProductSalesExists(id); + if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.PREPARE.getStatus(), sales.getStatus())) { + throw exception(WM_PRODUCT_SALES_NOT_PREPARE); + } + return sales; + } + + private void validateCodeUnique(Long id, String code) { + MesWmProductSalesDO sales = productSalesMapper.selectByCode(code); + if (sales == null) { + return; + } + if (ObjUtil.notEqual(id, sales.getId())) { + throw exception(WM_PRODUCT_SALES_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailService.java new file mode 100644 index 000000000..1c012e42b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailService.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnissue; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.detail.MesWmReturnIssueDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 生产退料明细 Service 接口 + */ +public interface MesWmReturnIssueDetailService { + + /** + * 创建生产退料明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnIssueDetail(@Valid MesWmReturnIssueDetailSaveReqVO createReqVO); + + /** + * 更新生产退料明细 + * + * @param updateReqVO 更新信息 + */ + void updateReturnIssueDetail(@Valid MesWmReturnIssueDetailSaveReqVO updateReqVO); + + /** + * 删除生产退料明细 + * + * @param id 编号 + */ + void deleteReturnIssueDetail(Long id); + + /** + * 获得生产退料明细 + * + * @param id 编号 + * @return 生产退料明细 + */ + MesWmReturnIssueDetailDO getReturnIssueDetail(Long id); + + /** + * 根据行 ID 获取明细列表 + * + * @param lineId 行 ID + * @return 明细列表 + */ + List getReturnIssueDetailListByLineId(Long lineId); + + /** + * 根据退料单 ID 获取明细列表 + * + * @param issueId 退料单 ID + * @return 明细列表 + */ + List getReturnIssueDetailListByIssueId(Long issueId); + + /** + * 根据退料单 ID 删除明细 + * + * @param issueId 退料单 ID + */ + void deleteReturnIssueDetailByIssueId(Long issueId); + + /** + * 根据行 ID 删除明细 + * + * @param lineId 行 ID + */ + void deleteReturnIssueDetailByLineId(Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java new file mode 100644 index 000000000..f0a8781d1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java @@ -0,0 +1,139 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnissue; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.detail.MesWmReturnIssueDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue.MesWmReturnIssueDetailMapper; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_DETAIL_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED; + +/** + * MES 生产退料明细 Service 实现类 + */ +@Service +@Validated +public class MesWmReturnIssueDetailServiceImpl implements MesWmReturnIssueDetailService { + + @Resource + private MesWmReturnIssueDetailMapper issueDetailMapper; + + @Resource + @Lazy + private MesWmReturnIssueLineService issueLineService; + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + @Resource + @Lazy + private MesWmMaterialStockService materialStockService; + + @Override + public Long createReturnIssueDetail(MesWmReturnIssueDetailSaveReqVO createReqVO) { + validateReturnIssueDetailSaveData(createReqVO); + + // 插入 + MesWmReturnIssueDetailDO detail = BeanUtils.toBean(createReqVO, MesWmReturnIssueDetailDO.class); + issueDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateReturnIssueDetail(MesWmReturnIssueDetailSaveReqVO updateReqVO) { + // 校验存在 + validateReturnIssueDetailExists(updateReqVO.getId()); + validateReturnIssueDetailSaveData(updateReqVO); + + // 更新 + MesWmReturnIssueDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnIssueDetailDO.class); + issueDetailMapper.updateById(updateObj); + } + + @Override + public void deleteReturnIssueDetail(Long id) { + // 校验存在 + validateReturnIssueDetailExists(id); + // 删除 + issueDetailMapper.deleteById(id); + } + + @Override + public MesWmReturnIssueDetailDO getReturnIssueDetail(Long id) { + return issueDetailMapper.selectById(id); + } + + @Override + public List getReturnIssueDetailListByLineId(Long lineId) { + return issueDetailMapper.selectListByLineId(lineId); + } + + @Override + public List getReturnIssueDetailListByIssueId(Long issueId) { + return issueDetailMapper.selectListByIssueId(issueId); + } + + @Override + public void deleteReturnIssueDetailByIssueId(Long issueId) { + issueDetailMapper.deleteByIssueId(issueId); + } + + @Override + public void deleteReturnIssueDetailByLineId(Long lineId) { + issueDetailMapper.deleteByLineId(lineId); + } + + private void validateReturnIssueDetailExists(Long id) { + if (issueDetailMapper.selectById(id) == null) { + throw exception(WM_RETURN_ISSUE_DETAIL_NOT_EXISTS); + } + } + + /** + * 校验保存时的关联数据 + */ + private void validateReturnIssueDetailSaveData(MesWmReturnIssueDetailSaveReqVO reqVO) { + // 校验父数据存在 + MesWmReturnIssueLineDO line = issueLineService.validateReturnIssueLineExists(reqVO.getLineId()); + // 校验仓库、库区、库位的关联关系 + warehouseAreaService.validateWarehouseAreaExists( + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); + // 校验库位物料/批次混放规则 + materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId()); + // 校验明细总数量不超过行数量(排除自身) + validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), reqVO.getId(), line); + } + + /** + * 校验明细总数量不超过行数量 + * + * @param lineId 行 ID + * @param newQuantity 本次新增/修改的数量 + * @param excludeDetailId 排除的明细 ID(更新时排除自身,新增时传 null) + * @param line 退料单行 + */ + private void validateDetailQuantityNotExceed(Long lineId, BigDecimal newQuantity, + Long excludeDetailId, MesWmReturnIssueLineDO line) { + // 计算已有明细总数量(排除自身) + List details = issueDetailMapper.selectListByLineId(lineId); + BigDecimal existingTotal = CollectionUtils.getSumValue(details, + detail -> excludeDetailId != null && excludeDetailId.equals(detail.getId()) + ? BigDecimal.ZERO : detail.getQuantity(), + BigDecimal::add, BigDecimal.ZERO); + // 校验:已有 + 本次 <= 行数量 + if (existingTotal.add(newQuantity).compareTo(line.getQuantity()) > 0) { + throw exception(WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineService.java new file mode 100644 index 000000000..6a8786f5c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineService.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWmReturnIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWmReturnIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; +import java.util.List; + +/** + * MES 生产退料单行 Service 接口 + */ +public interface MesWmReturnIssueLineService { + + /** + * 创建生产退料单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnIssueLine(@Valid MesWmReturnIssueLineSaveReqVO createReqVO); + + /** + * 更新生产退料单行 + * + * @param updateReqVO 更新信息 + */ + void updateReturnIssueLine(@Valid MesWmReturnIssueLineSaveReqVO updateReqVO); + + /** + * 删除生产退料单行 + * + * @param id 编号 + */ + void deleteReturnIssueLine(Long id); + + /** + * 获得生产退料单行 + * + * @param id 编号 + * @return 生产退料单行 + */ + MesWmReturnIssueLineDO getReturnIssueLine(Long id); + + /** + * 获得生产退料单行分页 + * + * @param pageReqVO 分页查询 + * @return 生产退料单行分页 + */ + PageResult getReturnIssueLinePage(MesWmReturnIssueLinePageReqVO pageReqVO); + + /** + * 根据退料单 ID 获取行列表 + * + * @param issueId 退料单 ID + * @return 行列表 + */ + List getReturnIssueLineListByIssueId(Long issueId); + + /** + * 根据退料单 ID 删除行 + * + * @param issueId 退料单 ID + */ + void deleteReturnIssueLineByIssueId(Long issueId); + + /** + * 校验生产退料单行是否存在 + * + * @param id 编号 + * @return 生产退料单行 + */ + MesWmReturnIssueLineDO validateReturnIssueLineExists(Long id); + + /** + * 刷新退料单下所有行的质量状态(退料类型变更时调用) + * + * @param issueId 退料单 ID + * @param issueType 退料类型 + */ + void updateReturnIssueQualityStatusByIssueId(Long issueId, Integer issueType); + + /** + * RQC 检验完成后,根据合格品/不合格品数量更新生产退料单行 + * + *

拆分逻辑: + *

    + *
  • 全部合格:直接更新行的 qualityStatus 为合格
  • + *
  • 全部不合格:直接更新行的 qualityStatus 为不合格
  • + *
  • 部分合格部分不合格:拆分原行(原行改为合格+数量=合格数,新增一行不合格+数量=不合格数)
  • + *
+ * 同时检查退料单下所有行是否都已检验完毕,若全检完则将退料单状态设为待上架。 + * + * @param sourceLineId 来源行 ID + * @param sourceDocId 来源退料单 ID + * @param checkResult 检验结果 + * @param qualifiedQuantity 合格品数量 + * @param unqualifiedQuantity 不合格品数量 + */ + void updateReturnIssueLineWhenRqcFinish(Long sourceLineId, Long sourceDocId, Integer checkResult, + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java new file mode 100644 index 000000000..81449acb1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java @@ -0,0 +1,201 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnissue; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWmReturnIssueLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.line.MesWmReturnIssueLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue.MesWmReturnIssueLineMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_LINE_NOT_EXISTS; + +/** + * MES 生产退料单行 Service 实现类 + */ +@Service +@Validated +public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineService { + + @Resource + private MesWmReturnIssueLineMapper issueLineMapper; + + @Resource + @Lazy + private MesWmReturnIssueService issueService; + @Resource + private MesMdItemService itemService; + @Resource + @Lazy + private MesWmReturnIssueDetailService issueDetailService; + + @Override + public Long createReturnIssueLine(MesWmReturnIssueLineSaveReqVO createReqVO) { + // 校验数据 + MesWmReturnIssueDO issue = validateReturnIssueLineSaveData(createReqVO); + + // 插入 + MesWmReturnIssueLineDO line = BeanUtils.toBean(createReqVO, MesWmReturnIssueLineDO.class); + line.setQualityStatus(calculateQualityStatus(line.getRqcCheckFlag(), issue.getType())); // 质量状态自动赋值 + issueLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateReturnIssueLine(MesWmReturnIssueLineSaveReqVO updateReqVO) { + // 校验存在 + validateReturnIssueLineExists(updateReqVO.getId()); + // 校验数据 + MesWmReturnIssueDO issue = validateReturnIssueLineSaveData(updateReqVO); + + // 更新 + MesWmReturnIssueLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnIssueLineDO.class); + updateObj.setQualityStatus(calculateQualityStatus(updateObj.getRqcCheckFlag(), issue.getType())); // 质量状态自动赋值 + issueLineMapper.updateById(updateObj); + } + + @Override + public void deleteReturnIssueLine(Long id) { + // 校验存在 + MesWmReturnIssueLineDO line = validateReturnIssueLineExists(id); + // 校验主单为草稿状态才允许删除行 + issueService.validateReturnIssueExistsAndPrepare(line.getIssueId()); + // 级联删除该行的明细 + issueDetailService.deleteReturnIssueDetailByLineId(id); + // 删除行 + issueLineMapper.deleteById(id); + } + + @Override + public MesWmReturnIssueLineDO getReturnIssueLine(Long id) { + return issueLineMapper.selectById(id); + } + + @Override + public PageResult getReturnIssueLinePage(MesWmReturnIssueLinePageReqVO pageReqVO) { + return issueLineMapper.selectPage(pageReqVO); + } + + @Override + public List getReturnIssueLineListByIssueId(Long issueId) { + return issueLineMapper.selectListByIssueId(issueId); + } + + @Override + public void deleteReturnIssueLineByIssueId(Long issueId) { + issueLineMapper.deleteByIssueId(issueId); + } + + @Override + public MesWmReturnIssueLineDO validateReturnIssueLineExists(Long id) { + MesWmReturnIssueLineDO line = issueLineMapper.selectById(id); + if (line == null) { + throw exception(WM_RETURN_ISSUE_LINE_NOT_EXISTS); + } + return line; + } + + /** + * 校验保存时的关联数据 + */ + private MesWmReturnIssueDO validateReturnIssueLineSaveData(MesWmReturnIssueLineSaveReqVO reqVO) { + // 校验父数据存在 + 草稿状态 + MesWmReturnIssueDO issue = issueService.validateReturnIssueExistsAndPrepare(reqVO.getIssueId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + return issue; + } + + @Override + public void updateReturnIssueQualityStatusByIssueId(Long issueId, Integer issueType) { + List lines = issueLineMapper.selectListByIssueId(issueId); + for (MesWmReturnIssueLineDO line : lines) { + Integer newStatus = calculateQualityStatus(line.getRqcCheckFlag(), issueType); + if (ObjUtil.notEqual(newStatus, line.getQualityStatus())) { + issueLineMapper.updateById(new MesWmReturnIssueLineDO() + .setId(line.getId()).setQualityStatus(newStatus)); + } + } + } + + /** + * 根据 rqcCheckFlag 和退料类型,计算质量状态 + * + * @param rqcCheckFlag 是否需要质检 + * @param issueType 退料类型 + * @return 质量状态 + */ + private Integer calculateQualityStatus(Boolean rqcCheckFlag, Integer issueType) { + if (Boolean.TRUE.equals(rqcCheckFlag)) { + return MesWmQualityStatusEnum.PENDING.getStatus(); // 待检 + } + if (MesWmReturnIssueTypeEnum.REMAINDER.getType().equals(issueType)) { + return MesWmQualityStatusEnum.PASS.getStatus(); // 合格(余料退回直接合格) + } + return MesWmQualityStatusEnum.FAIL.getStatus(); // 不合格 + } + + @Override + public void updateReturnIssueLineWhenRqcFinish(Long sourceLineId, Long sourceDocId, Integer checkResult, + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity) { + MesWmReturnIssueLineDO sourceLine = validateReturnIssueLineExists(sourceLineId); + boolean hasUnqualified = unqualifiedQuantity != null && unqualifiedQuantity.compareTo(BigDecimal.ZERO) > 0; + boolean hasQualified = qualifiedQuantity != null && qualifiedQuantity.compareTo(BigDecimal.ZERO) > 0; + + // 1. 根据合格/不合格品数量,更新退料单行的质量状态 + if (!hasUnqualified) { + // 1.A 情况一:全部合格 + issueLineMapper.updateById(new MesWmReturnIssueLineDO() + .setId(sourceLineId).setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus())); + } else if (!hasQualified) { + // 1.B 情况二:全部不合格 + issueLineMapper.updateById(new MesWmReturnIssueLineDO() + .setId(sourceLineId).setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus())); + } else { + // 1.C 情况三:部分合格部分不合格 → 拆分行 + // 1.C.1 新增一行不合格品 + MesWmReturnIssueLineDO unqualifiedLine = new MesWmReturnIssueLineDO() + .setIssueId(sourceLine.getIssueId()) + .setMaterialStockId(sourceLine.getMaterialStockId()) + .setItemId(sourceLine.getItemId()) + .setQuantity(unqualifiedQuantity) + .setBatchId(sourceLine.getBatchId()) + .setRqcId(sourceLine.getRqcId()) + .setRqcCheckFlag(sourceLine.getRqcCheckFlag()) + .setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) + .setRemark(sourceLine.getRemark()); + issueLineMapper.insert(unqualifiedLine); + // 1.C.2 更新原行为合格品(数量调整为合格数量) + issueLineMapper.updateById(new MesWmReturnIssueLineDO() + .setId(sourceLineId) + .setQuantity(qualifiedQuantity) + .setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus())); + } + + // 2. 检查退料单下是否还有待检验的行,若全检完则将退料单状态设为"待上架" + if (sourceDocId != null) { + List allLines = issueLineMapper.selectListByIssueId(sourceDocId); + boolean allInspected = !CollUtil.contains(allLines, + line -> Objects.equals(line.getQualityStatus(), MesWmQualityStatusEnum.PENDING.getStatus())); + if (allInspected) { + issueService.updateReturnIssueStatus(sourceDocId, MesWmReturnIssueStatusEnum.APPROVING.getStatus()); + } + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueService.java new file mode 100644 index 000000000..fb7a69d84 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueService.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnissue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.MesWmReturnIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.MesWmReturnIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDO; +import jakarta.validation.Valid; + +/** + * MES 生产退料单 Service 接口 + */ +public interface MesWmReturnIssueService { + + /** + * 创建生产退料单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnIssue(@Valid MesWmReturnIssueSaveReqVO createReqVO); + + /** + * 修改生产退料单 + * + * @param updateReqVO 修改信息 + */ + void updateReturnIssue(@Valid MesWmReturnIssueSaveReqVO updateReqVO); + + /** + * 删除生产退料单 + * + * @param id 编号 + */ + void deleteReturnIssue(Long id); + + /** + * 获得生产退料单 + * + * @param id 编号 + * @return 生产退料单 + */ + MesWmReturnIssueDO getReturnIssue(Long id); + + /** + * 获得生产退料单分页 + * + * @param pageReqVO 分页参数 + * @return 生产退料单分页 + */ + PageResult getReturnIssuePage(MesWmReturnIssuePageReqVO pageReqVO); + + /** + * 校验生产退料单是否存在 + * + * @param id 编号 + * @return 生产退料单 + */ + MesWmReturnIssueDO validateReturnIssueExists(Long id); + + /** + * 校验生产退料单存在且为准备中状态 + * + * @param id 编号 + * @return 生产退料单 + */ + MesWmReturnIssueDO validateReturnIssueExistsAndPrepare(Long id); + + /** + * 提交生产退料单(草稿 → 待检验/待上架) + * + * @param id 编号 + */ + void submitReturnIssue(Long id); + + /** + * 入库上架(待上架 → 待执行退料) + * + * @param id 编号 + */ + void stockReturnIssue(Long id); + + /** + * 完成退料(待执行退料 → 已完成),更新库存台账 + * + * @param id 编号 + */ + void finishReturnIssue(Long id); + + /** + * 取消生产退料单(任意非已完成/已取消状态 → 已取消) + * + * @param id 编号 + */ + void cancelReturnIssue(Long id); + + /** + * 更新生产退料单状态(供外部模块联动调用,如 RQC 检验完成后) + * + * @param id 编号 + * @param status 目标状态 + */ + void updateReturnIssueStatus(Long id, Integer status); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java new file mode 100644 index 000000000..361ee803e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java @@ -0,0 +1,296 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnissue; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.MesWmReturnIssuePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.MesWmReturnIssueSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue.MesWmReturnIssueMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 生产退料单 Service 实现类 + */ +@Service +@Validated +public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService { + + @Resource + private MesWmReturnIssueMapper issueMapper; + + @Resource + private MesWmReturnIssueLineService issueLineService; + @Resource + private MesWmReturnIssueDetailService issueDetailService; + @Resource + private MesMdWorkstationService workstationService; + @Resource + private MesProWorkOrderService workOrderService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmTransactionService wmTransactionService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createReturnIssue(MesWmReturnIssueSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateReturnIssueSaveData(createReqVO); + + // 2. 插入主表 + MesWmReturnIssueDO issue = BeanUtils.toBean(createReqVO, MesWmReturnIssueDO.class); + issue.setStatus(MesWmReturnIssueStatusEnum.PREPARE.getStatus()); + issueMapper.insert(issue); + return issue.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateReturnIssue(MesWmReturnIssueSaveReqVO updateReqVO) { + // 1.1 校验存在 + 准备中状态 + MesWmReturnIssueDO oldIssue = validateReturnIssueExistsAndPrepare(updateReqVO.getId()); + // 1.2 校验关联数据 + validateReturnIssueSaveData(updateReqVO); + + // 2. 更新主表 + MesWmReturnIssueDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnIssueDO.class); + issueMapper.updateById(updateObj); + + // 3. 退料类型变更时,刷新所有行的质量状态 + if (ObjUtil.notEqual(oldIssue.getType(), updateReqVO.getType())) { + issueLineService.updateReturnIssueQualityStatusByIssueId(updateReqVO.getId(), updateReqVO.getType()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteReturnIssue(Long id) { + // 1. 校验存在 + 准备中状态 + validateReturnIssueExistsAndPrepare(id); + + // 2.1 级联删除明细 + issueDetailService.deleteReturnIssueDetailByIssueId(id); + // 2.2 级联删除行 + issueLineService.deleteReturnIssueLineByIssueId(id); + // 2.3 删除主表 + issueMapper.deleteById(id); + } + + @Override + public MesWmReturnIssueDO getReturnIssue(Long id) { + return issueMapper.selectById(id); + } + + @Override + public PageResult getReturnIssuePage(MesWmReturnIssuePageReqVO pageReqVO) { + return issueMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitReturnIssue(Long id) { + // 1.1 校验存在 + 草稿状态 + validateReturnIssueExistsAndPrepare(id); + // 1.2 校验至少有一条行 + List lines = issueLineService.getReturnIssueLineListByIssueId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_RETURN_ISSUE_NO_LINE); + } + + // 2.1 确定目标状态:1)有待检验物料 → 待检验状态;2)无待检验物料 → 待上架状态 + boolean hasPendingQc = CollUtil.contains(lines, + line -> MesWmQualityStatusEnum.PENDING.getStatus().equals(line.getQualityStatus())); + Integer targetStatus = hasPendingQc ? MesWmReturnIssueStatusEnum.CONFIRMED.getStatus() + : MesWmReturnIssueStatusEnum.APPROVING.getStatus(); + // 2.2 提交(草稿 → 待检验/待上架) + issueMapper.updateById(new MesWmReturnIssueDO().setId(id).setStatus(targetStatus)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockReturnIssue(Long id) { + // 1.1 校验存在 + 待上架状态 + MesWmReturnIssueDO issue = validateReturnIssueExists(id); + if (ObjUtil.notEqual(MesWmReturnIssueStatusEnum.APPROVING.getStatus(), issue.getStatus())) { + throw exception(WM_RETURN_ISSUE_NOT_APPROVING); + } + // 1.2 检查每个行的明细数量是否完成上架 + List lines = issueLineService.getReturnIssueLineListByIssueId(id); + if (CollUtil.isNotEmpty(lines)) { + // 批量查询所有明细 + List allDetails = issueDetailService.getReturnIssueDetailListByIssueId(id); + Map> detailMap = CollectionUtils.convertMultiMap( + allDetails, MesWmReturnIssueDetailDO::getLineId); + // 检查每行的明细数量 + for (MesWmReturnIssueLineDO line : lines) { + List details = detailMap.getOrDefault(line.getId(), List.of()); + BigDecimal totalDetailQuantity = CollectionUtils.getSumValue(details, + MesWmReturnIssueDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + // 对比行数量与明细总数量,不满足直接抛出 + if (line.getQuantity().compareTo(totalDetailQuantity) > 0) { + MesMdItemDO item = itemService.validateItemExists(line.getItemId()); + throw exception(WM_RETURN_ISSUE_DETAIL_QUANTITY_MISMATCH, + item.getCode() + " " + item.getName() + " 未完成上架"); + } + } + } + + // 2. 入库上架(待上架 → 待执行退料) + issueMapper.updateById(new MesWmReturnIssueDO() + .setId(id).setStatus(MesWmReturnIssueStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishReturnIssue(Long id) { + // 1. 校验存在 + 待执行退料状态 + MesWmReturnIssueDO issue = validateReturnIssueExists(id); + if (ObjUtil.notEqual(MesWmReturnIssueStatusEnum.APPROVED.getStatus(), issue.getStatus())) { + throw exception(WM_RETURN_ISSUE_NOT_APPROVED); + } + + // 2. 遍历所有明细,创建库存事务(增加库存 + 记录流水) + createTransactionList(issue); + + // 3. 更新退料单状态 + issueMapper.updateById(new MesWmReturnIssueDO() + .setId(id).setStatus(MesWmReturnIssueStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmReturnIssueDO issue) { + // 1. 查询虚拟线边库 + MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); + + // 2. 遍历明细,每条明细产生 OUT(虚拟线边库扣减)+ IN(实际仓库增加) + List details = issueDetailService.getReturnIssueDetailListByIssueId(issue.getId()); + for (MesWmReturnIssueDetailDO detail : details) { + // 2.1 先从虚拟线边库出库(库存减少) + Long outTransactionId = wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity().negate()) // 库存减少 + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) + .setWarehouseId(virtualWarehouse.getId()).setLocationId(virtualLocation.getId()).setAreaId(virtualArea.getId()) + .setCheckFlag(false) // 线边库允许负库存 + .setBizType(MesBizTypeConstants.WM_RETURN_ISSUE).setBizId(issue.getId()) + .setBizCode(issue.getCode()).setBizLineId(detail.getLineId())); + // 2.2 再入实际仓库(库存增加) + wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity()) // 库存增加(退料回仓) + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setBizType(MesBizTypeConstants.WM_RETURN_ISSUE).setBizId(issue.getId()) + .setBizCode(issue.getCode()).setBizLineId(detail.getLineId()) + .setRelatedTransactionId(outTransactionId)); // 关联出库事务 + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelReturnIssue(Long id) { + // 校验存在 + MesWmReturnIssueDO issue = validateReturnIssueExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(issue.getStatus(), + MesWmReturnIssueStatusEnum.FINISHED.getStatus(), + MesWmReturnIssueStatusEnum.CANCELED.getStatus())) { + throw exception(WM_RETURN_ISSUE_CANCEL_NOT_ALLOWED); + } + + // 取消 + issueMapper.updateById(new MesWmReturnIssueDO() + .setId(id).setStatus(MesWmReturnIssueStatusEnum.CANCELED.getStatus())); + } + + @Override + public MesWmReturnIssueDO validateReturnIssueExists(Long id) { + MesWmReturnIssueDO issue = issueMapper.selectById(id); + if (issue == null) { + throw exception(WM_RETURN_ISSUE_NOT_EXISTS); + } + return issue; + } + + /** + * 校验生产退料单存在且为准备中状态 + */ + @Override + public MesWmReturnIssueDO validateReturnIssueExistsAndPrepare(Long id) { + MesWmReturnIssueDO issue = validateReturnIssueExists(id); + if (ObjUtil.notEqual(MesWmReturnIssueStatusEnum.PREPARE.getStatus(), issue.getStatus())) { + throw exception(WM_RETURN_ISSUE_NOT_PREPARE); + } + return issue; + } + + @Override + public void updateReturnIssueStatus(Long id, Integer status) { + validateReturnIssueExists(id); + issueMapper.updateById(new MesWmReturnIssueDO().setId(id).setStatus(status)); + } + + /** + * 校验编码唯一性 + */ + private void validateCodeUnique(Long id, String code) { + MesWmReturnIssueDO issue = issueMapper.selectByCode(code); + if (issue == null) { + return; + } + if (ObjUtil.notEqual(id, issue.getId())) { + throw exception(WM_RETURN_ISSUE_CODE_DUPLICATE); + } + } + + /** + * 校验保存时的关联数据 + */ + private void validateReturnIssueSaveData(MesWmReturnIssueSaveReqVO reqVO) { + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + if (reqVO.getWorkstationId() != null) { + workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailService.java new file mode 100644 index 000000000..83d923a1f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailService.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnsales; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail.MesWmReturnSalesDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 销售退货明细 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmReturnSalesDetailService { + + /** + * 创建销售退货明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnSalesDetail(@Valid MesWmReturnSalesDetailSaveReqVO createReqVO); + + /** + * 更新销售退货明细 + * + * @param updateReqVO 更新信息 + */ + void updateReturnSalesDetail(@Valid MesWmReturnSalesDetailSaveReqVO updateReqVO); + + /** + * 删除销售退货明细 + * + * @param id 编号 + */ + void deleteReturnSalesDetail(Long id); + + /** + * 获得销售退货明细 + * + * @param id 编号 + * @return 销售退货明细 + */ + MesWmReturnSalesDetailDO getReturnSalesDetail(Long id); + + /** + * 根据行ID获取明细列表 + * + * @param lineId 行ID + * @return 明细列表 + */ + List getReturnSalesDetailListByLineId(Long lineId); + + /** + * 根据退货单ID获取明细列表 + * + * @param returnId 退货单ID + * @return 明细列表 + */ + List getReturnSalesDetailListByReturnId(Long returnId); + + /** + * 根据退货单ID删除明细 + * + * @param returnId 退货单ID + */ + void deleteReturnSalesDetailByReturnId(Long returnId); + + /** + * 根据行ID删除明细(行删除时级联) + * + * @param lineId 行ID + */ + void deleteReturnSalesDetailByLineId(Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java new file mode 100644 index 000000000..cce30639b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnsales; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.detail.MesWmReturnSalesDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesDetailMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 销售退货明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetailService { + + @Resource + private MesWmReturnSalesDetailMapper returnSalesDetailMapper; + + @Resource + @Lazy + private MesWmReturnSalesLineService returnSalesLineService; + @Resource + @Lazy + private MesWmReturnSalesService returnSalesService; + + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + + @Resource + @Lazy + private MesWmMaterialStockService materialStockService; + + @Override + public Long createReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO createReqVO) { + validateReturnSalesDetailSaveData(createReqVO); + + // 插入 + MesWmReturnSalesDetailDO detail = BeanUtils.toBean(createReqVO, MesWmReturnSalesDetailDO.class); + returnSalesDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO updateReqVO) { + // 校验存在 + validateReturnSalesDetailExists(updateReqVO.getId()); + validateReturnSalesDetailSaveData(updateReqVO); + + // 更新 + MesWmReturnSalesDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesDetailDO.class); + returnSalesDetailMapper.updateById(updateObj); + } + + @Override + public void deleteReturnSalesDetail(Long id) { + // 校验存在 + MesWmReturnSalesDetailDO detail = validateReturnSalesDetailExists(id); + // 校验退货单为待上架状态才允许删除明细 + validateReturnSalesStatusApproved(detail.getReturnId()); + + // 删除 + returnSalesDetailMapper.deleteById(id); + } + + @Override + public MesWmReturnSalesDetailDO getReturnSalesDetail(Long id) { + return returnSalesDetailMapper.selectById(id); + } + + @Override + public List getReturnSalesDetailListByLineId(Long lineId) { + return returnSalesDetailMapper.selectListByLineId(lineId); + } + + @Override + public List getReturnSalesDetailListByReturnId(Long returnId) { + return returnSalesDetailMapper.selectListByReturnId(returnId); + } + + @Override + public void deleteReturnSalesDetailByReturnId(Long returnId) { + returnSalesDetailMapper.deleteByReturnId(returnId); + } + + @Override + public void deleteReturnSalesDetailByLineId(Long lineId) { + returnSalesDetailMapper.deleteByLineId(lineId); + } + + private MesWmReturnSalesDetailDO validateReturnSalesDetailExists(Long id) { + MesWmReturnSalesDetailDO detail = returnSalesDetailMapper.selectById(id); + if (detail == null) { + throw exception(WM_RETURN_SALES_DETAIL_NOT_EXISTS); + } + return detail; + } + + /** + * 校验退货单为待上架状态(明细操作仅允许在待上架状态) + */ + private void validateReturnSalesStatusApproved(Long returnId) { + MesWmReturnSalesDO returnSales = returnSalesService.validateReturnSalesExists(returnId); + if (ObjUtil.notEqual(MesWmReturnSalesStatusEnum.APPROVED.getStatus(), returnSales.getStatus())) { + throw exception(WM_RETURN_SALES_STATUS_NOT_APPROVED); + } + } + + /** + * 校验保存时的关联数据 + */ + private void validateReturnSalesDetailSaveData(MesWmReturnSalesDetailSaveReqVO reqVO) { + // 校验父数据存在 + MesWmReturnSalesLineDO line = returnSalesLineService.validateReturnSalesLineExists(reqVO.getLineId()); + // 校验退货单为待上架状态 + validateReturnSalesStatusApproved(line.getReturnId()); + // 校验仓库、库区、库位的关联关系 + warehouseAreaService.validateWarehouseAreaExists( + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); + // 校验库位物料/批次混放规则 + materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId()); + // 校验明细总数量不超过行数量(排除自身) + validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), reqVO.getId(), line); + } + + /** + * 校验明细总数量不超过行数量 + * + * @param lineId 行 ID + * @param newQuantity 本次新增/修改的数量 + * @param excludeDetailId 排除的明细 ID(更新时排除自身,新增时传 null) + * @param line 退货单行 + */ + private void validateDetailQuantityNotExceed(Long lineId, BigDecimal newQuantity, + Long excludeDetailId, MesWmReturnSalesLineDO line) { + // 计算已有明细总数量(排除自身) + List details = returnSalesDetailMapper.selectListByLineId(lineId); + BigDecimal existingTotal = CollectionUtils.getSumValue(details, + detail -> excludeDetailId != null && excludeDetailId.equals(detail.getId()) + ? BigDecimal.ZERO : detail.getQuantity(), + BigDecimal::add, BigDecimal.ZERO); + // 校验:已有 + 本次 <= 行数量 + if (existingTotal.add(newQuantity).compareTo(line.getQuantity()) > 0) { + throw exception(WM_RETURN_SALES_DETAIL_QUANTITY_EXCEED); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineService.java new file mode 100644 index 000000000..496d4a185 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineService.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnsales; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; +import java.util.List; + +/** + * MES 销售退货单行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmReturnSalesLineService { + + /** + * 创建销售退货单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnSalesLine(@Valid MesWmReturnSalesLineSaveReqVO createReqVO); + + /** + * 更新销售退货单行 + * + * @param updateReqVO 更新信息 + */ + void updateReturnSalesLine(@Valid MesWmReturnSalesLineSaveReqVO updateReqVO); + + /** + * 删除销售退货单行 + * + * @param id 编号 + */ + void deleteReturnSalesLine(Long id); + + /** + * 获得销售退货单行 + * + * @param id 编号 + * @return 销售退货单行 + */ + MesWmReturnSalesLineDO getReturnSalesLine(Long id); + + /** + * 获得销售退货单行分页 + * + * @param pageReqVO 分页查询 + * @return 销售退货单行分页 + */ + PageResult getReturnSalesLinePage(MesWmReturnSalesLinePageReqVO pageReqVO); + + /** + * 根据退货单ID获取行列表 + * + * @param returnId 退货单ID + * @return 行列表 + */ + List getReturnSalesLineListByReturnId(Long returnId); + + /** + * 根据退货单ID删除行 + * + * @param returnId 退货单ID + */ + void deleteReturnSalesLineByReturnId(Long returnId); + + /** + * 校验销售退货单行是否存在 + * + * @param id 编号 + * @return 销售退货单行 + */ + MesWmReturnSalesLineDO validateReturnSalesLineExists(Long id); + + /** + * 批量更新退货单行的质量状态 + * + * @param returnId 退货单ID + * @param qualityStatus 质量状态 + */ + void updateQualityStatusByReturnId(Long returnId, Integer qualityStatus); + + /** + * RQC 检验完成后,根据合格品/不合格品数量更新销售退货单行 + * + *

拆分逻辑: + *

    + *
  • 全部合格:直接更新行的 qualityStatus 为合格
  • + *
  • 全部不合格:直接更新行的 qualityStatus 为不合格
  • + *
  • 部分合格部分不合格:拆分原行(原行改为合格+数量=合格数,新增一行不合格+数量=不合格数)
  • + *
+ * 同时检查退货单下所有行是否都已检验完毕,若全检完则将退货单状态设为待上架。 + * + * @param sourceLineId 来源行 ID + * @param sourceDocId 来源退货单 ID + * @param checkResult 检验结果 + * @param qualifiedQuantity 合格品数量 + * @param unqualifiedQuantity 不合格品数量 + */ + void updateReturnSalesLineWhenRqcFinish(Long sourceLineId, Long sourceDocId, Integer checkResult, + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java new file mode 100644 index 000000000..634b168d3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java @@ -0,0 +1,205 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnsales; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_BATCH_REQUIRED; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_SALES_LINE_NOT_EXISTS; + +/** + * MES 销售退货单行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineService { + + @Resource + private MesWmReturnSalesLineMapper returnSalesLineMapper; + + @Resource + @Lazy + private MesWmReturnSalesService returnSalesService; + @Resource + private MesMdItemService itemService; + @Resource + @Lazy + private MesWmReturnSalesDetailService returnSalesDetailService; + + @Override + public Long createReturnSalesLine(MesWmReturnSalesLineSaveReqVO createReqVO) { + validateLineSaveData(createReqVO); + + // 插入 + MesWmReturnSalesLineDO line = BeanUtils.toBean(createReqVO, MesWmReturnSalesLineDO.class); + // 质量状态自动赋值 + line.setQualityStatus(calculateQualityStatus(line.getRqcCheckFlag())); + returnSalesLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateReturnSalesLine(MesWmReturnSalesLineSaveReqVO updateReqVO) { + // 校验存在 + validateReturnSalesLineExists(updateReqVO.getId()); + validateLineSaveData(updateReqVO); + + // 更新 + MesWmReturnSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesLineDO.class); + // 质量状态自动赋值 + updateObj.setQualityStatus(calculateQualityStatus(updateObj.getRqcCheckFlag())); + returnSalesLineMapper.updateById(updateObj); + } + + /** + * 校验保存时的关联数据 + */ + private void validateLineSaveData(MesWmReturnSalesLineSaveReqVO reqVO) { + // 校验退货单存在 + 草稿状态 + returnSalesService.validateReturnSalesExistsAndPrepare(reqVO.getReturnId()); + // 校验物料存在 + 批次管理 + validateItemBatchManagement(reqVO.getItemId(), reqVO.getBatchId()); + } + + @Override + public void deleteReturnSalesLine(Long id) { + // 校验存在 + MesWmReturnSalesLineDO line = validateReturnSalesLineExists(id); + // 校验主单为草稿状态才允许删除行 + returnSalesService.validateReturnSalesExistsAndPrepare(line.getReturnId()); + // 级联删除该行的明细 + returnSalesDetailService.deleteReturnSalesDetailByLineId(id); + // 删除行 + returnSalesLineMapper.deleteById(id); + } + + @Override + public MesWmReturnSalesLineDO getReturnSalesLine(Long id) { + return returnSalesLineMapper.selectById(id); + } + + @Override + public PageResult getReturnSalesLinePage(MesWmReturnSalesLinePageReqVO pageReqVO) { + return returnSalesLineMapper.selectPage(pageReqVO); + } + + @Override + public List getReturnSalesLineListByReturnId(Long returnId) { + return returnSalesLineMapper.selectListByReturnId(returnId); + } + + @Override + public void deleteReturnSalesLineByReturnId(Long returnId) { + returnSalesLineMapper.deleteByReturnId(returnId); + } + + @Override + public MesWmReturnSalesLineDO validateReturnSalesLineExists(Long id) { + MesWmReturnSalesLineDO line = returnSalesLineMapper.selectById(id); + if (line == null) { + throw exception(WM_RETURN_SALES_LINE_NOT_EXISTS); + } + return line; + } + + @Override + public void updateQualityStatusByReturnId(Long returnId, Integer qualityStatus) { + List lines = returnSalesLineMapper.selectListByReturnId(returnId); + for (MesWmReturnSalesLineDO line : lines) { + Integer newStatus = calculateQualityStatus(line.getRqcCheckFlag()); + if (ObjUtil.notEqual(newStatus, line.getQualityStatus())) { + returnSalesLineMapper.updateById(new MesWmReturnSalesLineDO() + .setId(line.getId()).setQualityStatus(newStatus)); + } + } + } + + private Integer calculateQualityStatus(Boolean rqcCheckFlag) { + if (Boolean.TRUE.equals(rqcCheckFlag)) { + return MesWmQualityStatusEnum.PENDING.getStatus(); // 待检 + } + return MesWmQualityStatusEnum.PASS.getStatus(); // 不需检验,默认合格 + } + + /** + * 校验物料批次管理 + * + * @param itemId 物料ID + * @param batchId 批次ID + */ + private void validateItemBatchManagement(Long itemId, Long batchId) { + MesMdItemDO item = itemService.validateItemExists(itemId); + // 如果物料启用了批次管理,则必须选择批次 + if (Boolean.TRUE.equals(item.getBatchFlag()) && batchId == null) { + throw exception(MD_ITEM_BATCH_REQUIRED); + } + } + + @Override + public void updateReturnSalesLineWhenRqcFinish(Long sourceLineId, Long sourceDocId, Integer checkResult, + BigDecimal qualifiedQuantity, BigDecimal unqualifiedQuantity) { + MesWmReturnSalesLineDO sourceLine = validateReturnSalesLineExists(sourceLineId); + boolean hasUnqualified = unqualifiedQuantity != null && unqualifiedQuantity.compareTo(BigDecimal.ZERO) > 0; + boolean hasQualified = qualifiedQuantity != null && qualifiedQuantity.compareTo(BigDecimal.ZERO) > 0; + + // 1. 根据合格/不合格品数量,更新退货单行的质量状态 + if (!hasUnqualified) { + // 1.A 情况一:全部合格 + returnSalesLineMapper.updateById(new MesWmReturnSalesLineDO() + .setId(sourceLineId).setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus())); + } else if (!hasQualified) { + // 1.B 情况二:全部不合格 + returnSalesLineMapper.updateById(new MesWmReturnSalesLineDO() + .setId(sourceLineId).setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus())); + } else { + // 1.C 情况三:部分合格部分不合格 → 拆分行 + // 1.C.1 新增一行不合格品 + MesWmReturnSalesLineDO unqualifiedLine = new MesWmReturnSalesLineDO() + .setReturnId(sourceLine.getReturnId()) + .setItemId(sourceLine.getItemId()) + .setQuantity(unqualifiedQuantity) + .setBatchId(sourceLine.getBatchId()) + .setRqcId(sourceLine.getRqcId()) + .setRqcCheckFlag(sourceLine.getRqcCheckFlag()) + .setQualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) + .setRemark(sourceLine.getRemark()); + returnSalesLineMapper.insert(unqualifiedLine); + // 1.C.2 更新原行为合格品 + returnSalesLineMapper.updateById(new MesWmReturnSalesLineDO() + .setId(sourceLineId) + .setQuantity(qualifiedQuantity) + .setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus())); + } + + // 2. 检查退货单下是否还有待检验的行,若全检完则将退货单状态设为"待上架" + if (sourceDocId != null) { + List allLines = returnSalesLineMapper.selectListByReturnId(sourceDocId); + boolean allInspected = !CollUtil.contains(allLines, + line -> Objects.equals(line.getQualityStatus(), MesWmQualityStatusEnum.PENDING.getStatus())); + if (allInspected) { + returnSalesService.updateReturnSalesStatus(sourceDocId, MesWmReturnSalesStatusEnum.APPROVING.getStatus()); + } + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesService.java new file mode 100644 index 000000000..1c06437e7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesService.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnsales; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; +import jakarta.validation.Valid; + +/** + * MES 销售退货单 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmReturnSalesService { + + /** + * 创建销售退货单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnSales(@Valid MesWmReturnSalesSaveReqVO createReqVO); + + /** + * 修改销售退货单 + * + * @param updateReqVO 修改信息 + */ + void updateReturnSales(@Valid MesWmReturnSalesSaveReqVO updateReqVO); + + /** + * 删除销售退货单 + * + * @param id 编号 + */ + void deleteReturnSales(Long id); + + /** + * 获得销售退货单 + * + * @param id 编号 + * @return 销售退货单 + */ + MesWmReturnSalesDO getReturnSales(Long id); + + /** + * 获得销售退货单分页 + * + * @param pageReqVO 分页参数 + * @return 销售退货单分页 + */ + PageResult getReturnSalesPage(MesWmReturnSalesPageReqVO pageReqVO); + + /** + * 校验销售退货单是否存在 + * + * @param id 编号 + * @return 销售退货单 + */ + MesWmReturnSalesDO validateReturnSalesExists(Long id); + + /** + * 校验销售退货单存在且为草稿状态 + * + * @param id 编号 + * @return 销售退货单 + */ + MesWmReturnSalesDO validateReturnSalesExistsAndPrepare(Long id); + + /** + * 提交销售退货单(草稿 -> 待执行) + * + * @param id 编号 + */ + void submitReturnSales(Long id); + + /** + * 执行退货(待执行 -> 待上架) + * + * @param id 编号 + */ + void finishReturnSales(Long id); + + /** + * 执行上架(待上架 -> 已完成),更新库存台账 + * + * @param id 编号 + */ + void stockReturnSales(Long id); + + /** + * 取消销售退货单(任意非已完成/已取消状态 -> 已取消) + * + * @param id 编号 + */ + void cancelReturnSales(Long id); + + /** + * 更新销售退货单状态(供外部模块联动调用,如 RQC 检验完成后) + * + * @param id 编号 + * @param status 目标状态 + */ + void updateReturnSalesStatus(Long id, Integer status); + + /** + * 校验销售退货单的数量:每行明细数量之和是否等于行退货数量 + * + * @param id 编号 + * @return 是否全部一致 + */ + Boolean checkReturnSalesQuantity(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java new file mode 100644 index 000000000..2347dfda6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java @@ -0,0 +1,276 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnsales; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 销售退货单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmReturnSalesServiceImpl implements MesWmReturnSalesService { + + @Resource + private MesWmReturnSalesMapper returnSalesMapper; + + @Resource + private MesWmReturnSalesLineService returnSalesLineService; + @Resource + private MesWmReturnSalesDetailService returnSalesDetailService; + @Resource + private MesMdClientService clientService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmTransactionService wmTransactionService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createReturnSales(MesWmReturnSalesSaveReqVO createReqVO) { + // 1. 校验关联数据 + validateSaveData(createReqVO); + + // 2. 插入主表 + MesWmReturnSalesDO returnSales = BeanUtils.toBean(createReqVO, MesWmReturnSalesDO.class); + returnSales.setStatus(MesWmReturnSalesStatusEnum.PREPARE.getStatus()); + returnSalesMapper.insert(returnSales); + return returnSales.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateReturnSales(MesWmReturnSalesSaveReqVO updateReqVO) { + // 1.1 校验存在 + 准备中状态 + validateReturnSalesExistsAndPrepare(updateReqVO.getId()); + // 1.2 校验关联数据 + validateSaveData(updateReqVO); + + // 2. 更新主表 + MesWmReturnSalesDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesDO.class); + returnSalesMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteReturnSales(Long id) { + // 1. 校验存在 + 准备中状态 + validateReturnSalesExistsAndPrepare(id); + + // 2.1 级联删除明细 + returnSalesDetailService.deleteReturnSalesDetailByReturnId(id); + // 2.2 级联删除行 + returnSalesLineService.deleteReturnSalesLineByReturnId(id); + // 2.3 删除主表 + returnSalesMapper.deleteById(id); + } + + @Override + public MesWmReturnSalesDO getReturnSales(Long id) { + return returnSalesMapper.selectById(id); + } + + @Override + public PageResult getReturnSalesPage(MesWmReturnSalesPageReqVO pageReqVO) { + return returnSalesMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitReturnSales(Long id) { + // 1.1 校验存在 + 草稿状态 + validateReturnSalesExistsAndPrepare(id); + // 1.2 校验至少有一条行 + List lines = returnSalesLineService.getReturnSalesLineListByReturnId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_RETURN_SALES_NO_LINE); + } + + // 2.1 确定目标状态:1)有待检验物料 → 待检验状态;2)无待检验物料 → 待执行状态 + boolean hasPendingQc = CollUtil.contains(lines, + line -> MesWmQualityStatusEnum.PENDING.getStatus().equals(line.getQualityStatus())); + Integer targetStatus = hasPendingQc ? MesWmReturnSalesStatusEnum.CONFIRMED.getStatus() + : MesWmReturnSalesStatusEnum.APPROVING.getStatus(); + // 2.2 提交(草稿 -> 待检验/待执行) + returnSalesMapper.updateById(new MesWmReturnSalesDO() + .setId(id).setStatus(targetStatus)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishReturnSales(Long id) { + // 1.1 校验存在 + 待执行状态 + MesWmReturnSalesDO returnSales = validateReturnSalesExists(id); + if (ObjUtil.notEqual(MesWmReturnSalesStatusEnum.APPROVING.getStatus(), returnSales.getStatus())) { + throw exception(WM_RETURN_SALES_STATUS_NOT_APPROVING); + } + // 1.2 校验至少有一条行 + List lines = returnSalesLineService.getReturnSalesLineListByReturnId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_RETURN_SALES_NO_LINE); + } + // 2. 执行退货(待执行 -> 待上架) + returnSalesMapper.updateById(new MesWmReturnSalesDO() + .setId(id).setStatus(MesWmReturnSalesStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockReturnSales(Long id) { + // 1.1 校验存在 + 待上架状态 + MesWmReturnSalesDO returnSales = validateReturnSalesExists(id); + if (ObjUtil.notEqual(MesWmReturnSalesStatusEnum.APPROVED.getStatus(), returnSales.getStatus())) { + throw exception(WM_RETURN_SALES_STATUS_NOT_APPROVED); + } + // 1.2 检查每个行的明细数量是否完成上架 + List lines = returnSalesLineService.getReturnSalesLineListByReturnId(id); + if (CollUtil.isNotEmpty(lines)) { + // 批量查询所有明细 + List allDetails = returnSalesDetailService.getReturnSalesDetailListByReturnId(id); + Map> detailMap = CollectionUtils.convertMultiMap( + allDetails, MesWmReturnSalesDetailDO::getLineId); + // 检查每行的明细数量 + for (MesWmReturnSalesLineDO line : lines) { + List details = detailMap.getOrDefault(line.getId(), List.of()); + BigDecimal totalDetailQuantity = CollectionUtils.getSumValue(details, + MesWmReturnSalesDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + // 对比行数量与明细总数量,不满足直接抛出 + if (line.getQuantity().compareTo(totalDetailQuantity) > 0) { + MesMdItemDO item = itemService.validateItemExists(line.getItemId()); + throw exception(WM_RETURN_SALES_DETAIL_QUANTITY_MISMATCH, + item.getCode() + " " + item.getName() + " 未完成上架"); + } + } + } + + // 2. 遍历所有明细,创建库存事务(增加库存 + 记录流水) + createTransactionList(returnSales); + + // 3. 更新退货单状态 + returnSalesMapper.updateById(new MesWmReturnSalesDO() + .setId(id).setStatus(MesWmReturnSalesStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmReturnSalesDO returnSales) { + List details = returnSalesDetailService.getReturnSalesDetailListByReturnId(returnSales.getId()); + wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity()) // 入库数量为正数 + .setBatchId(detail.getBatchId()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setBizType(MesBizTypeConstants.WM_RETURN_SALES).setBizId(returnSales.getId()) + .setBizCode(returnSales.getCode()).setBizLineId(detail.getLineId()))); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelReturnSales(Long id) { + // 校验存在 + MesWmReturnSalesDO returnSales = validateReturnSalesExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(returnSales.getStatus(), + MesWmReturnSalesStatusEnum.FINISHED.getStatus(), + MesWmReturnSalesStatusEnum.CANCELED.getStatus())) { + throw exception(WM_RETURN_SALES_CANCEL_NOT_ALLOWED); + } + + // 取消 + returnSalesMapper.updateById(new MesWmReturnSalesDO() + .setId(id).setStatus(MesWmReturnSalesStatusEnum.CANCELED.getStatus())); + } + + @Override + public Boolean checkReturnSalesQuantity(Long id) { + List lines = returnSalesLineService.getReturnSalesLineListByReturnId(id); + for (MesWmReturnSalesLineDO line : lines) { + List details = returnSalesDetailService.getReturnSalesDetailListByLineId(line.getId()); + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmReturnSalesDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) { + return false; + } + } + return true; + } + + @Override + public MesWmReturnSalesDO validateReturnSalesExists(Long id) { + MesWmReturnSalesDO returnSales = returnSalesMapper.selectById(id); + if (returnSales == null) { + throw exception(WM_RETURN_SALES_NOT_EXISTS); + } + return returnSales; + } + + /** + * 校验销售退货单存在且为准备中状态 + */ + @Override + public MesWmReturnSalesDO validateReturnSalesExistsAndPrepare(Long id) { + MesWmReturnSalesDO returnSales = validateReturnSalesExists(id); + if (ObjUtil.notEqual(MesWmReturnSalesStatusEnum.PREPARE.getStatus(), returnSales.getStatus())) { + throw exception(WM_RETURN_SALES_STATUS_NOT_PREPARE); + } + return returnSales; + } + + @Override + public void updateReturnSalesStatus(Long id, Integer status) { + validateReturnSalesExists(id); + returnSalesMapper.updateById(new MesWmReturnSalesDO().setId(id).setStatus(status)); + } + + /** + * 校验编码唯一性 + */ + private void validateCodeUnique(Long id, String code) { + MesWmReturnSalesDO returnSales = returnSalesMapper.selectByCode(code); + if (returnSales == null) { + return; + } + if (ObjUtil.notEqual(id, returnSales.getId())) { + throw exception(WM_RETURN_SALES_CODE_DUPLICATE); + } + } + + /** + * 校验保存时的关联数据 + */ + private void validateSaveData(MesWmReturnSalesSaveReqVO reqVO) { + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + clientService.validateClientExists(reqVO.getClientId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailService.java new file mode 100644 index 000000000..56c386920 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailService.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnvendor; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.detail.MesWmReturnVendorDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 供应商退货明细 Service 接口 + */ +public interface MesWmReturnVendorDetailService { + + /** + * 创建供应商退货明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnVendorDetail(@Valid MesWmReturnVendorDetailSaveReqVO createReqVO); + + /** + * 更新供应商退货明细 + * + * @param updateReqVO 更新信息 + */ + void updateReturnVendorDetail(@Valid MesWmReturnVendorDetailSaveReqVO updateReqVO); + + /** + * 删除供应商退货明细 + * + * @param id 编号 + */ + void deleteReturnVendorDetail(Long id); + + /** + * 获得供应商退货明细 + * + * @param id 编号 + * @return 供应商退货明细 + */ + MesWmReturnVendorDetailDO getReturnVendorDetail(Long id); + + /** + * 根据行ID获取明细列表 + * + * @param lineId 行ID + * @return 明细列表 + */ + List getReturnVendorDetailListByLineId(Long lineId); + + /** + * 根据退货单ID获取明细列表 + * + * @param returnId 退货单ID + * @return 明细列表 + */ + List getReturnVendorDetailListByReturnId(Long returnId); + + /** + * 根据退货单ID删除明细 + * + * @param returnId 退货单ID + */ + void deleteReturnVendorDetailByReturnId(Long returnId); + + /** + * 根据行ID删除明细 + * + * @param lineId 行ID + */ + void deleteReturnVendorDetailByLineId(Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java new file mode 100644 index 000000000..91e4b7c68 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java @@ -0,0 +1,143 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnvendor; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.detail.MesWmReturnVendorDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor.MesWmReturnVendorDetailMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 供应商退货明细 Service 实现类 + */ +@Service +@Validated +public class MesWmReturnVendorDetailServiceImpl implements MesWmReturnVendorDetailService { + + @Resource + private MesWmReturnVendorDetailMapper returnVendorDetailMapper; + + @Resource + @Lazy + private MesWmReturnVendorLineService returnVendorLineService; + + @Resource + private MesMdItemService itemService; + + @Resource + private MesWmMaterialStockService materialStockService; + + @Override + public Long createReturnVendorDetail(MesWmReturnVendorDetailSaveReqVO createReqVO) { + // 校验数据 + validateDetailSaveData(createReqVO); + + // 插入 + MesWmReturnVendorDetailDO detail = BeanUtils.toBean(createReqVO, MesWmReturnVendorDetailDO.class); + returnVendorDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateReturnVendorDetail(MesWmReturnVendorDetailSaveReqVO updateReqVO) { + // 校验存在 + validateReturnVendorDetailExists(updateReqVO.getId()); + // 校验数据 + validateDetailSaveData(updateReqVO); + + // 更新 + MesWmReturnVendorDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnVendorDetailDO.class); + returnVendorDetailMapper.updateById(updateObj); + } + + /** + * 校验明细创建/修改的公共数据 + */ + private void validateDetailSaveData(MesWmReturnVendorDetailSaveReqVO reqVO) { + // 校验父数据(行)存在 + MesWmReturnVendorLineDO line = returnVendorLineService.validateReturnVendorLineExists(reqVO.getLineId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + // 校验物料与行物料一致 + validateItemConsistency(reqVO.getItemId(), line); + // 校验库存记录存在且物料一致 + validateMaterialStock(reqVO.getMaterialStockId(), line); + } + + @Override + public void deleteReturnVendorDetail(Long id) { + // 校验存在 + validateReturnVendorDetailExists(id); + // 删除 + returnVendorDetailMapper.deleteById(id); + } + + @Override + public MesWmReturnVendorDetailDO getReturnVendorDetail(Long id) { + return returnVendorDetailMapper.selectById(id); + } + + @Override + public List getReturnVendorDetailListByLineId(Long lineId) { + return returnVendorDetailMapper.selectListByLineId(lineId); + } + + @Override + public List getReturnVendorDetailListByReturnId(Long returnId) { + return returnVendorDetailMapper.selectListByReturnId(returnId); + } + + @Override + public void deleteReturnVendorDetailByReturnId(Long returnId) { + returnVendorDetailMapper.deleteByReturnId(returnId); + } + + @Override + public void deleteReturnVendorDetailByLineId(Long lineId) { + returnVendorDetailMapper.deleteByLineId(lineId); + } + + private void validateReturnVendorDetailExists(Long id) { + if (returnVendorDetailMapper.selectById(id) == null) { + throw exception(WM_RETURN_VENDOR_DETAIL_NOT_EXISTS); + } + } + + /** + * 校验明细物料与行物料一致 + */ + private void validateItemConsistency(Long detailItemId, MesWmReturnVendorLineDO line) { + if (ObjUtil.notEqual(detailItemId, line.getItemId())) { + throw exception(WM_RETURN_VENDOR_DETAIL_ITEM_MISMATCH); + } + } + + /** + * 校验库存记录存在且物料与行物料一致 + */ + private void validateMaterialStock(Long materialStockId, MesWmReturnVendorLineDO line) { + if (materialStockId == null) { + return; + } + MesWmMaterialStockDO stock = materialStockService.getMaterialStock(materialStockId); + if (stock == null) { + throw exception(WM_MATERIAL_STOCK_NOT_EXISTS); + } + if (ObjUtil.notEqual(stock.getItemId(), line.getItemId())) { + throw exception(WM_RETURN_VENDOR_DETAIL_ITEM_MISMATCH); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineService.java new file mode 100644 index 000000000..96ddaaf50 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineService.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnvendor; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 供应商退货单行 Service 接口 + */ +public interface MesWmReturnVendorLineService { + + /** + * 创建供应商退货单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnVendorLine(@Valid MesWmReturnVendorLineSaveReqVO createReqVO); + + /** + * 更新供应商退货单行 + * + * @param updateReqVO 更新信息 + */ + void updateReturnVendorLine(@Valid MesWmReturnVendorLineSaveReqVO updateReqVO); + + /** + * 删除供应商退货单行 + * + * @param id 编号 + */ + void deleteReturnVendorLine(Long id); + + /** + * 获得供应商退货单行 + * + * @param id 编号 + * @return 供应商退货单行 + */ + MesWmReturnVendorLineDO getReturnVendorLine(Long id); + + /** + * 获得供应商退货单行分页 + * + * @param pageReqVO 分页查询 + * @return 供应商退货单行分页 + */ + PageResult getReturnVendorLinePage(MesWmReturnVendorLinePageReqVO pageReqVO); + + /** + * 根据退货单ID获取行列表 + * + * @param returnId 退货单ID + * @return 行列表 + */ + List getReturnVendorLineListByReturnId(Long returnId); + + /** + * 根据退货单ID删除行 + * + * @param returnId 退货单ID + */ + void deleteReturnVendorLineByReturnId(Long returnId); + + /** + * 校验供应商退货单行是否存在 + * + * @param id 编号 + * @return 供应商退货单行 + */ + MesWmReturnVendorLineDO validateReturnVendorLineExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java new file mode 100644 index 000000000..71b821321 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnvendor; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor.MesWmReturnVendorLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_VENDOR_LINE_NOT_EXISTS; + +/** + * MES 供应商退货单行 Service 实现类 + */ +@Service +@Validated +public class MesWmReturnVendorLineServiceImpl implements MesWmReturnVendorLineService { + + @Resource + private MesWmReturnVendorLineMapper returnVendorLineMapper; + + @Resource + @Lazy + private MesWmReturnVendorService returnVendorService; + @Resource + @Lazy + private MesWmReturnVendorDetailService returnVendorDetailService; + @Resource + private MesMdItemService itemService; + + @Override + public Long createReturnVendorLine(MesWmReturnVendorLineSaveReqVO createReqVO) { + // 校验数据 + validateReturnVendorLineSaveData(createReqVO); + + // 插入 + MesWmReturnVendorLineDO line = BeanUtils.toBean(createReqVO, MesWmReturnVendorLineDO.class); + returnVendorLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateReturnVendorLine(MesWmReturnVendorLineSaveReqVO updateReqVO) { + // 校验存在 + validateReturnVendorLineExists(updateReqVO.getId()); + // 校验数据 + validateReturnVendorLineSaveData(updateReqVO); + + // 更新 + MesWmReturnVendorLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnVendorLineDO.class); + returnVendorLineMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteReturnVendorLine(Long id) { + // 1.1 校验存在 + MesWmReturnVendorLineDO line = validateReturnVendorLineExists(id); + // 1.2 校验父数据为草稿状态 + returnVendorService.validateReturnVendorExistsAndPrepare(line.getReturnId()); + + // 2.1 级联删除该行下的明细 + returnVendorDetailService.deleteReturnVendorDetailByLineId(id); + // 2.2 删除行 + returnVendorLineMapper.deleteById(id); + } + + @Override + public MesWmReturnVendorLineDO getReturnVendorLine(Long id) { + return returnVendorLineMapper.selectById(id); + } + + @Override + public PageResult getReturnVendorLinePage(MesWmReturnVendorLinePageReqVO pageReqVO) { + return returnVendorLineMapper.selectPage(pageReqVO); + } + + @Override + public List getReturnVendorLineListByReturnId(Long returnId) { + return returnVendorLineMapper.selectListByReturnId(returnId); + } + + @Override + public void deleteReturnVendorLineByReturnId(Long returnId) { + returnVendorLineMapper.deleteByReturnId(returnId); + } + + @Override + public MesWmReturnVendorLineDO validateReturnVendorLineExists(Long id) { + MesWmReturnVendorLineDO line = returnVendorLineMapper.selectById(id); + if (line == null) { + throw exception(WM_RETURN_VENDOR_LINE_NOT_EXISTS); + } + return line; + } + + private void validateReturnVendorLineSaveData(MesWmReturnVendorLineSaveReqVO reqVO) { + // 校验父数据存在且为草稿状态 + returnVendorService.validateReturnVendorExistsAndPrepare(reqVO.getReturnId()); + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorService.java new file mode 100644 index 000000000..9a74087e1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorService.java @@ -0,0 +1,112 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnvendor; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDO; +import jakarta.validation.Valid; + +/** + * MES 供应商退货单 Service 接口 + */ +public interface MesWmReturnVendorService { + + /** + * 创建供应商退货单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReturnVendor(@Valid MesWmReturnVendorSaveReqVO createReqVO); + + /** + * 修改供应商退货单 + * + * @param updateReqVO 修改信息 + */ + void updateReturnVendor(@Valid MesWmReturnVendorSaveReqVO updateReqVO); + + /** + * 删除供应商退货单 + * + * @param id 编号 + */ + void deleteReturnVendor(Long id); + + /** + * 获得供应商退货单 + * + * @param id 编号 + * @return 供应商退货单 + */ + MesWmReturnVendorDO getReturnVendor(Long id); + + /** + * 获得供应商退货单分页 + * + * @param pageReqVO 分页参数 + * @return 供应商退货单分页 + */ + PageResult getReturnVendorPage(MesWmReturnVendorPageReqVO pageReqVO); + + /** + * 校验供应商退货单是否存在 + * + * @param id 编号 + * @return 供应商退货单 + */ + MesWmReturnVendorDO validateReturnVendorExists(Long id); + + /** + * 提交供应商退货单(草稿 -> 待拣货) + * + * @param id 编号 + */ + void submitReturnVendor(Long id); + + /** + * 执行拣货(待拣货 -> 待执行退货) + * + * @param id 编号 + */ + void stockReturnVendor(Long id); + + /** + * 执行退货/出库(待执行退货 -> 已完成),更新库存台账 + * + * @param id 编号 + */ + void finishReturnVendor(Long id); + + /** + * 取消供应商退货单(任意非已完成/已取消状态 -> 已取消) + * + * @param id 编号 + */ + void cancelReturnVendor(Long id); + + /** + * 校验供应商退货单的数量:每行明细数量之和是否等于行退货数量 + * + * @param id 编号 + * @return 是否全部一致 + */ + Boolean checkReturnVendorQuantity(Long id); + + /** + * 查询指定供应商的退货单数量 + * + * @param vendorId 供应商编号 + * @return 数量 + */ + Long getReturnVendorCountByVendorId(Long vendorId); + + /** + * 校验供应商退货单存在且为草稿状态 + * + * @param id 编号 + * @return 供应商退货单 + */ + MesWmReturnVendorDO validateReturnVendorExistsAndPrepare(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java new file mode 100644 index 000000000..c7ac68ac3 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java @@ -0,0 +1,243 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnvendor; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.MesWmReturnVendorSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor.MesWmReturnVendorMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnVendorStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 供应商退货单 Service 实现类 + */ +@Service +@Validated +public class MesWmReturnVendorServiceImpl implements MesWmReturnVendorService { + + @Resource + private MesWmReturnVendorMapper returnVendorMapper; + + @Resource + private MesWmReturnVendorLineService returnVendorLineService; + @Resource + private MesWmReturnVendorDetailService returnVendorDetailService; + @Resource + private MesMdVendorService vendorService; + @Resource + private MesWmTransactionService wmTransactionService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createReturnVendor(MesWmReturnVendorSaveReqVO createReqVO) { + // 1. 校验数据 + validateReturnVendorSaveData(createReqVO); + + // 2. 插入主表 + MesWmReturnVendorDO returnVendor = BeanUtils.toBean(createReqVO, MesWmReturnVendorDO.class); + returnVendor.setStatus(MesWmReturnVendorStatusEnum.PREPARE.getStatus()); + returnVendorMapper.insert(returnVendor); + return returnVendor.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateReturnVendor(MesWmReturnVendorSaveReqVO updateReqVO) { + // 1. 校验数据 + validateReturnVendorSaveData(updateReqVO); + + // 2. 更新主表 + MesWmReturnVendorDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnVendorDO.class); + returnVendorMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteReturnVendor(Long id) { + // 1. 校验存在 + 准备中状态 + validateReturnVendorExistsAndPrepare(id); + + // 2.1 级联删除明细 + returnVendorDetailService.deleteReturnVendorDetailByReturnId(id); + // 2.2 级联删除行 + returnVendorLineService.deleteReturnVendorLineByReturnId(id); + // 2.3 删除主表 + returnVendorMapper.deleteById(id); + } + + @Override + public MesWmReturnVendorDO getReturnVendor(Long id) { + return returnVendorMapper.selectById(id); + } + + @Override + public PageResult getReturnVendorPage(MesWmReturnVendorPageReqVO pageReqVO) { + return returnVendorMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitReturnVendor(Long id) { + // 校验存在 + 草稿状态 + validateReturnVendorExistsAndPrepare(id); + // 校验至少有一条行 + List lines = returnVendorLineService.getReturnVendorLineListByReturnId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_RETURN_VENDOR_NO_LINE); + } + + // 提交(草稿 -> 待拣货) + returnVendorMapper.updateById(new MesWmReturnVendorDO() + .setId(id).setStatus(MesWmReturnVendorStatusEnum.APPROVING.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockReturnVendor(Long id) { + // 校验存在 + MesWmReturnVendorDO returnVendor = validateReturnVendorExists(id); + if (ObjUtil.notEqual(MesWmReturnVendorStatusEnum.APPROVING.getStatus(), returnVendor.getStatus())) { + throw exception(WM_RETURN_VENDOR_STATUS_INVALID); + } + // 执行拣货(待拣货 -> 待执行退货) + returnVendorMapper.updateById(new MesWmReturnVendorDO() + .setId(id).setStatus(MesWmReturnVendorStatusEnum.APPROVED.getStatus())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishReturnVendor(Long id) { + // 1.1 校验存在 + MesWmReturnVendorDO returnVendor = validateReturnVendorExists(id); + if (ObjUtil.notEqual(MesWmReturnVendorStatusEnum.APPROVED.getStatus(), returnVendor.getStatus())) { + throw exception(WM_RETURN_VENDOR_STATUS_INVALID); + } + // 1.2 校验明细不为空 + List details = returnVendorDetailService.getReturnVendorDetailListByReturnId(id); + if (CollUtil.isEmpty(details)) { + throw exception(WM_RETURN_VENDOR_NO_DETAIL); + } + + // 2. 遍历所有明细,创建库存事务(扣减库存 + 记录流水) + createTransactionList(returnVendor, details); + + // 3. 更新退货单状态 + returnVendorMapper.updateById(new MesWmReturnVendorDO() + .setId(id).setStatus(MesWmReturnVendorStatusEnum.FINISHED.getStatus())); + } + + private void createTransactionList(MesWmReturnVendorDO returnVendor, List details) { + wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId()) + .setQuantity(detail.getQuantity().negate()) // 出库数量为负数 + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) + .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) + .setVendorId(returnVendor.getVendorId()) + .setBizType(MesBizTypeConstants.WM_RETURN_VENDOR).setBizId(returnVendor.getId()) + .setBizCode(returnVendor.getCode()).setBizLineId(detail.getLineId()))); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelReturnVendor(Long id) { + // 校验存在 + MesWmReturnVendorDO returnVendor = validateReturnVendorExists(id); + // 已完成和已取消不允许取消 + if (ObjectUtils.equalsAny(returnVendor.getStatus(), + MesWmReturnVendorStatusEnum.FINISHED.getStatus(), + MesWmReturnVendorStatusEnum.CANCELED.getStatus())) { + throw exception(WM_RETURN_VENDOR_CANCEL_NOT_ALLOWED); + } + + // 取消 + returnVendorMapper.updateById(new MesWmReturnVendorDO() + .setId(id).setStatus(MesWmReturnVendorStatusEnum.CANCELED.getStatus())); + } + + @Override + public Boolean checkReturnVendorQuantity(Long id) { + List lines = returnVendorLineService.getReturnVendorLineListByReturnId(id); + for (MesWmReturnVendorLineDO line : lines) { + List details = returnVendorDetailService.getReturnVendorDetailListByLineId(line.getId()); + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmReturnVendorDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) { + return false; + } + } + return true; + } + + @Override + public MesWmReturnVendorDO validateReturnVendorExists(Long id) { + MesWmReturnVendorDO returnVendor = returnVendorMapper.selectById(id); + if (returnVendor == null) { + throw exception(WM_RETURN_VENDOR_NOT_EXISTS); + } + return returnVendor; + } + + @Override + public MesWmReturnVendorDO validateReturnVendorExistsAndPrepare(Long id) { + MesWmReturnVendorDO returnVendor = validateReturnVendorExists(id); + if (ObjUtil.notEqual(MesWmReturnVendorStatusEnum.PREPARE.getStatus(), returnVendor.getStatus())) { + throw exception(WM_RETURN_VENDOR_STATUS_INVALID); + } + return returnVendor; + } + + /** + * 校验退货单创建/修改的公共数据 + */ + private void validateReturnVendorSaveData(MesWmReturnVendorSaveReqVO reqVO) { + // 校验存在 + 草稿状态(仅修改时) + if (reqVO.getId() != null) { + validateReturnVendorExistsAndPrepare(reqVO.getId()); + } + // 校验供应商存在 + vendorService.validateVendorExists(reqVO.getVendorId()); + // 校验编码唯一 + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + } + + /** + * 校验退货单编号唯一 + */ + private void validateCodeUnique(Long id, String code) { + MesWmReturnVendorDO existing = returnVendorMapper.selectByCode(code); + if (existing == null) { + return; + } + if (ObjUtil.notEqual(id, existing.getId())) { + throw exception(WM_RETURN_VENDOR_CODE_DUPLICATE); + } + } + + @Override + public Long getReturnVendorCountByVendorId(Long vendorId) { + return returnVendorMapper.selectCountByVendorId(vendorId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineService.java new file mode 100644 index 000000000..4fc969da6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineService.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.service.wm.salesnotice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line.MesWmSalesNoticeLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line.MesWmSalesNoticeLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 发货通知单行 Service 接口 + */ +public interface MesWmSalesNoticeLineService { + + /** + * 创建发货通知单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSalesNoticeLine(@Valid MesWmSalesNoticeLineSaveReqVO createReqVO); + + /** + * 修改发货通知单行 + * + * @param updateReqVO 修改信息 + */ + void updateSalesNoticeLine(@Valid MesWmSalesNoticeLineSaveReqVO updateReqVO); + + /** + * 删除发货通知单行 + * + * @param id 编号 + */ + void deleteSalesNoticeLine(Long id); + + /** + * 获得发货通知单行 + * + * @param id 编号 + * @return 发货通知单行 + */ + MesWmSalesNoticeLineDO getSalesNoticeLine(Long id); + + /** + * 获得发货通知单行分页 + * + * @param pageReqVO 分页参数 + * @return 发货通知单行分页 + */ + PageResult getSalesNoticeLinePage(MesWmSalesNoticeLinePageReqVO pageReqVO); + + /** + * 按通知单编号获得行列表 + * + * @param noticeId 通知单编号 + * @return 行列表 + */ + List getSalesNoticeLineListByNoticeId(Long noticeId); + + /** + * 按通知单编号批量删除行 + * + * @param noticeId 通知单编号 + */ + void deleteSalesNoticeLineByNoticeId(Long noticeId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineServiceImpl.java new file mode 100644 index 000000000..d71bffbce --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineServiceImpl.java @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.module.mes.service.wm.salesnotice; + +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line.MesWmSalesNoticeLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.line.MesWmSalesNoticeLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.salesnotice.MesWmSalesNoticeLineMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum.PREPARE; + +/** + * MES 发货通知单行 Service 实现类 + */ +@Service +@Validated +public class MesWmSalesNoticeLineServiceImpl implements MesWmSalesNoticeLineService { + + @Resource + private MesWmSalesNoticeLineMapper salesNoticeLineMapper; + + @Resource + @Lazy + private MesWmSalesNoticeService salesNoticeService; + + @Resource + private MesWmBatchService batchService; + + @Resource + private MesMdItemService itemService; + + @Override + public Long createSalesNoticeLine(MesWmSalesNoticeLineSaveReqVO createReqVO) { + // 校验数据 + validateLineSaveData(createReqVO); + + // 插入 + MesWmSalesNoticeLineDO line = BeanUtils.toBean(createReqVO, MesWmSalesNoticeLineDO.class); + fillBatchId(line); + salesNoticeLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateSalesNoticeLine(MesWmSalesNoticeLineSaveReqVO updateReqVO) { + // 校验存在 + MesWmSalesNoticeLineDO line = validateSalesNoticeLineExists(updateReqVO.getId()); + // 校验数据 + updateReqVO.setNoticeId(line.getNoticeId()); + validateLineSaveData(updateReqVO); + + // 更新 + MesWmSalesNoticeLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmSalesNoticeLineDO.class); + fillBatchId(updateObj); + salesNoticeLineMapper.updateById(updateObj); + } + + @Override + public void deleteSalesNoticeLine(Long id) { + // 校验存在 + MesWmSalesNoticeLineDO line = validateSalesNoticeLineExists(id); + // 校验父单据存在且为草稿状态 + validateNoticeStatusDraft(line.getNoticeId()); + + // 删除 + salesNoticeLineMapper.deleteById(id); + } + + @Override + public MesWmSalesNoticeLineDO getSalesNoticeLine(Long id) { + return salesNoticeLineMapper.selectById(id); + } + + @Override + public PageResult getSalesNoticeLinePage(MesWmSalesNoticeLinePageReqVO pageReqVO) { + return salesNoticeLineMapper.selectPage(pageReqVO); + } + + @Override + public List getSalesNoticeLineListByNoticeId(Long noticeId) { + return salesNoticeLineMapper.selectListByNoticeId(noticeId); + } + + @Override + public void deleteSalesNoticeLineByNoticeId(Long noticeId) { + salesNoticeLineMapper.deleteByNoticeId(noticeId); + } + + private MesWmSalesNoticeLineDO validateSalesNoticeLineExists(Long id) { + MesWmSalesNoticeLineDO line = salesNoticeLineMapper.selectById(id); + if (line == null) { + throw exception(WM_SALES_NOTICE_LINE_NOT_EXISTS); + } + return line; + } + + private void validateLineSaveData(MesWmSalesNoticeLineSaveReqVO reqVO) { + // 校验父单据存在且为草稿状态 + validateNoticeStatusDraft(reqVO.getNoticeId()); + // 校验物料存在 + if (reqVO.getItemId() != null) { + itemService.validateItemExists(reqVO.getItemId()); + } + } + + /** + * 校验父发货通知单存在且为草稿状态 + */ + private void validateNoticeStatusDraft(Long noticeId) { + MesWmSalesNoticeDO notice = salesNoticeService.getSalesNotice(noticeId); + if (notice == null) { + throw exception(WM_SALES_NOTICE_NOT_EXISTS); + } + if (ObjUtil.notEqual(PREPARE.getStatus(), notice.getStatus())) { + throw exception(WM_SALES_NOTICE_STATUS_NOT_ALLOW_UPDATE); + } + } + + /** + * 根据 batchCode 回填 batchId + */ + private void fillBatchId(MesWmSalesNoticeLineDO line) { + if (StrUtil.isEmpty(line.getBatchCode())) { + return; + } + MesWmBatchDO batch = batchService.getBatchByCode(line.getBatchCode()); + if (batch != null) { + line.setBatchId(batch.getId()); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java new file mode 100644 index 000000000..b471b57c7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java @@ -0,0 +1,91 @@ +package cn.iocoder.yudao.module.mes.service.wm.salesnotice; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 发货通知单 Service 接口 + */ +public interface MesWmSalesNoticeService { + + /** + * 创建发货通知单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSalesNotice(@Valid MesWmSalesNoticeSaveReqVO createReqVO); + + /** + * 修改发货通知单 + * + * @param updateReqVO 修改信息 + */ + void updateSalesNotice(@Valid MesWmSalesNoticeSaveReqVO updateReqVO); + + /** + * 删除发货通知单 + * + * @param id 编号 + */ + void deleteSalesNotice(Long id); + + /** + * 获得发货通知单 + * + * @param id 编号 + * @return 发货通知单 + */ + MesWmSalesNoticeDO getSalesNotice(Long id); + + /** + * 获得发货通知单分页 + * + * @param pageReqVO 分页参数 + * @return 发货通知单分页 + */ + PageResult getSalesNoticePage(MesWmSalesNoticePageReqVO pageReqVO); + + /** + * 提交发货通知单 + * + * @param id 编号 + */ + void submitSalesNotice(Long id); + + /** + * 获得发货通知单列表 + * + * @param ids 编号列表 + * @return 发货通知单列表 + */ + List getSalesNoticeList(Collection ids); + + /** + * 获得发货通知单 Map + * + * @param ids 编号列表 + * @return 发货通知单 Map + */ + default Map getSalesNoticeMap(Collection ids) { + return convertMap(getSalesNoticeList(ids), MesWmSalesNoticeDO::getId); + } + + /** + * 按状态获得发货通知单列表 + * + * @param status 状态 + * @return 发货通知单列表 + */ + List getSalesNoticeListByStatus(Integer status); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java new file mode 100644 index 000000000..9e82adc9e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.mes.service.wm.salesnotice; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSalesNoticeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.salesnotice.MesWmSalesNoticeMapper; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum.*; + +/** + * MES 发货通知单 Service 实现类 + */ +@Service +@Validated +@Slf4j +public class MesWmSalesNoticeServiceImpl implements MesWmSalesNoticeService { + + @Resource + private MesWmSalesNoticeMapper salesNoticeMapper; + + @Resource + private MesWmSalesNoticeLineService salesNoticeLineService; + + @Resource + private MesMdClientService clientService; + + @Override + public Long createSalesNotice(MesWmSalesNoticeSaveReqVO createReqVO) { + // 校验数据 + validateSalesNoticeSave(createReqVO); + + // 插入 + MesWmSalesNoticeDO notice = BeanUtils.toBean(createReqVO, MesWmSalesNoticeDO.class); + notice.setStatus(PREPARE.getStatus()); // 草稿状态 + salesNoticeMapper.insert(notice); + return notice.getId(); + } + + @Override + public void updateSalesNotice(MesWmSalesNoticeSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateSalesNoticeExistsAndDraft(updateReqVO.getId()); + // 校验数据 + validateSalesNoticeSave(updateReqVO); + + // 更新 + MesWmSalesNoticeDO updateObj = BeanUtils.toBean(updateReqVO, MesWmSalesNoticeDO.class); + salesNoticeMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSalesNotice(Long id) { + // 校验存在 + 草稿状态 + validateSalesNoticeExistsAndDraft(id); + + // 级联删除行 + salesNoticeLineService.deleteSalesNoticeLineByNoticeId(id); + // 删除 + salesNoticeMapper.deleteById(id); + } + + @Override + public MesWmSalesNoticeDO getSalesNotice(Long id) { + return salesNoticeMapper.selectById(id); + } + + @Override + public PageResult getSalesNoticePage(MesWmSalesNoticePageReqVO pageReqVO) { + return salesNoticeMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitSalesNotice(Long id) { + // 1.1 校验存在 + 草稿状态 + validateSalesNoticeExistsAndDraft(id); + // 1.2 检查是否有行项目 + List lines = salesNoticeLineService.getSalesNoticeLineListByNoticeId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_SALES_NOTICE_LINE_EMPTY); + } + + // 2. 更新状态:草稿 → 待出库 + salesNoticeMapper.updateById(new MesWmSalesNoticeDO() + .setId(id).setStatus(APPROVED.getStatus())); + } + + @Override + public List getSalesNoticeList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return salesNoticeMapper.selectByIds(ids); + } + + @Override + public List getSalesNoticeListByStatus(Integer status) { + if (status == null) { + return salesNoticeMapper.selectList(); + } + return salesNoticeMapper.selectListByStatus(status); + } + + private MesWmSalesNoticeDO validateSalesNoticeExists(Long id) { + MesWmSalesNoticeDO notice = salesNoticeMapper.selectById(id); + if (notice == null) { + throw exception(WM_SALES_NOTICE_NOT_EXISTS); + } + return notice; + } + + /** + * 校验发货通知单存在且为草稿状态 + */ + private MesWmSalesNoticeDO validateSalesNoticeExistsAndDraft(Long id) { + MesWmSalesNoticeDO notice = validateSalesNoticeExists(id); + if (ObjUtil.notEqual(PREPARE.getStatus(), notice.getStatus())) { + throw exception(WM_SALES_NOTICE_STATUS_NOT_ALLOW_DELETE); + } + return notice; + } + + private void validateSalesNoticeSave(MesWmSalesNoticeSaveReqVO saveReqVO) { + // 校验编码唯一 + validateNoticeCodeUnique(saveReqVO.getId(), saveReqVO.getNoticeCode()); + // 校验客户存在 + if (saveReqVO.getClientId() != null) { + clientService.validateClientExists(saveReqVO.getClientId()); + } + } + + private void validateNoticeCodeUnique(Long id, String noticeCode) { + MesWmSalesNoticeDO notice = salesNoticeMapper.selectByNoticeCode(noticeCode); + if (notice == null) { + return; + } + if (ObjUtil.notEqual(id, notice.getId())) { + throw exception(WM_SALES_NOTICE_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnService.java new file mode 100644 index 000000000..15e29d129 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnService.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.mes.service.wm.sn; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnGenerateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnGroupRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sn.MesWmSnDO; + +import java.util.List; + +/** + * MES SN 码 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmSnService { + + /** + * 批量生成 SN 码 + * + * @param reqVO 生成请求 + */ + void generateSnCodes(MesWmSnGenerateReqVO reqVO); + + /** + * 获得 SN 码分组分页(按 UUID 聚合) + * + * @param reqVO 分页查询 + * @return SN 码分组分页 + */ + PageResult getSnGroupPage(MesWmSnPageReqVO reqVO); + + /** + * 获得批次 SN 码列表 + * + * @param uuid 批次 UUID + * @return SN 码列表 + */ + List getSnListByUuid(String uuid); + + /** + * 批量删除 SN 码(按批次 UUID) + * + * @param uuid 批次 UUID + */ + void deleteSnByUuid(String uuid); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnServiceImpl.java new file mode 100644 index 000000000..85288c635 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnServiceImpl.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.service.wm.sn; + +import cn.hutool.core.util.IdUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnGenerateReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnGroupRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sn.MesWmSnDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.sn.MesWmSnMapper; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; + +/** + * MES SN 码 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +@Slf4j +public class MesWmSnServiceImpl implements MesWmSnService { + + @Resource + private MesWmSnMapper snMapper; + @Resource + private MesMdAutoCodeRecordService autoCodeRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void generateSnCodes(MesWmSnGenerateReqVO reqVO) { + List sns = new ArrayList<>(reqVO.getCount()); + // 生成批次 UUID + String uuid = IdUtil.fastSimpleUUID(); + // 批量生成 SN 码 + for (int i = 0; i < reqVO.getCount(); i++) { + String snCode = autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.WM_SN_CODE.getCode()); + sns.add(new MesWmSnDO().setUuid(uuid).setCode(snCode) + .setItemId(reqVO.getItemId()).setBatchCode(reqVO.getBatchCode()) + .setWorkOrderId(reqVO.getWorkOrderId())); + } + // 批量插入 + snMapper.insertBatch(sns); + } + + @Override + public PageResult getSnGroupPage(MesWmSnPageReqVO reqVO) { + return snMapper.selectPageGroupByUuid(reqVO); + } + + @Override + public List getSnListByUuid(String uuid) { + return snMapper.selectListByUuid(uuid); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSnByUuid(String uuid) { + snMapper.deleteByUuid(uuid); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanParamService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanParamService.java new file mode 100644 index 000000000..7b1ff7ba6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanParamService.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param.MesWmStockTakingPlanParamPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param.MesWmStockTakingPlanParamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanParamDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 盘点方案参数 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmStockTakingPlanParamService { + + /** + * 创建盘点方案参数 + * + * @param createReqVO 创建信息 + * @return 参数编号 + */ + Long createStockTakingPlanParam(@Valid MesWmStockTakingPlanParamSaveReqVO createReqVO); + + /** + * 更新盘点方案参数 + * + * @param updateReqVO 更新信息 + */ + void updateStockTakingPlanParam(@Valid MesWmStockTakingPlanParamSaveReqVO updateReqVO); + + /** + * 删除盘点方案参数 + * + * @param id 参数编号 + */ + void deleteStockTakingPlanParam(Long id); + + /** + * 获得盘点方案参数 + * + * @param id 参数编号 + * @return 盘点方案参数 + */ + MesWmStockTakingPlanParamDO getStockTakingPlanParam(Long id); + + /** + * 分页查询盘点方案参数 + * + * @param pageReqVO 分页查询条件 + * @return 盘点方案参数分页结果 + */ + PageResult getStockTakingPlanParamPage(MesWmStockTakingPlanParamPageReqVO pageReqVO); + + /** + * 根据盘点方案编号删除参数 + * + * @param planId 盘点方案编号 + */ + void deleteStockTakingPlanParamByPlanId(Long planId); + + /** + * 校验盘点方案参数是否存在 + * + * @param id 参数编号 + * @return 盘点方案参数 + */ + MesWmStockTakingPlanParamDO validateStockTakingPlanParamExists(Long id); + + /** + * 根据盘点方案编号获取参数列表 + * + * @param planId 盘点方案编号 + * @return 盘点方案参数列表 + */ + List getStockTakingPlanParamListByPlanId(Long planId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanParamServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanParamServiceImpl.java new file mode 100644 index 000000000..b37e6ed5e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanParamServiceImpl.java @@ -0,0 +1,98 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param.MesWmStockTakingPlanParamPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.param.MesWmStockTakingPlanParamSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanParamDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.plan.MesWmStockTakingPlanParamMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_STOCK_TAKING_PLAN_PARAM_NOT_EXISTS; + +/** + * MES 盘点方案参数 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmStockTakingPlanParamServiceImpl implements MesWmStockTakingPlanParamService { + + @Resource + private MesWmStockTakingPlanParamMapper stockTakingPlanParamMapper; + @Resource + @Lazy + private MesWmStockTakingPlanService stockTakingPlanService; + + @Override + public Long createStockTakingPlanParam(MesWmStockTakingPlanParamSaveReqVO createReqVO) { + // 校验盘点方案是否可编辑 + stockTakingPlanService.validateStockTakingPlanEditable(createReqVO.getPlanId()); + + // 创建盘点方案参数 + MesWmStockTakingPlanParamDO param = BeanUtils.toBean(createReqVO, MesWmStockTakingPlanParamDO.class); + stockTakingPlanParamMapper.insert(param); + return param.getId(); + } + + @Override + public void updateStockTakingPlanParam(MesWmStockTakingPlanParamSaveReqVO updateReqVO) { + // 校验盘点方案参数存在 + MesWmStockTakingPlanParamDO param = validateStockTakingPlanParamExists(updateReqVO.getId()); + // 校验盘点方案是否可编辑 + stockTakingPlanService.validateStockTakingPlanEditable(param.getPlanId()); + + // 更新盘点方案参数 + MesWmStockTakingPlanParamDO updateObj = BeanUtils.toBean(updateReqVO, MesWmStockTakingPlanParamDO.class); + updateObj.setPlanId(param.getPlanId()); + stockTakingPlanParamMapper.updateById(updateObj); + } + + @Override + public void deleteStockTakingPlanParam(Long id) { + // 校验盘点方案参数存在 + MesWmStockTakingPlanParamDO param = validateStockTakingPlanParamExists(id); + // 校验盘点方案是否可编辑 + stockTakingPlanService.validateStockTakingPlanEditable(param.getPlanId()); + + // 删除盘点方案参数 + stockTakingPlanParamMapper.deleteById(id); + } + + @Override + public MesWmStockTakingPlanParamDO getStockTakingPlanParam(Long id) { + return stockTakingPlanParamMapper.selectById(id); + } + + @Override + public PageResult getStockTakingPlanParamPage(MesWmStockTakingPlanParamPageReqVO pageReqVO) { + return stockTakingPlanParamMapper.selectPage(pageReqVO); + } + + @Override + public void deleteStockTakingPlanParamByPlanId(Long planId) { + stockTakingPlanParamMapper.deleteByPlanId(planId); + } + + @Override + public MesWmStockTakingPlanParamDO validateStockTakingPlanParamExists(Long id) { + MesWmStockTakingPlanParamDO param = stockTakingPlanParamMapper.selectById(id); + if (param == null) { + throw exception(WM_STOCK_TAKING_PLAN_PARAM_NOT_EXISTS); + } + return param; + } + + @Override + public List getStockTakingPlanParamListByPlanId(Long planId) { + return stockTakingPlanParamMapper.selectListByPlanId(planId); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanService.java new file mode 100644 index 000000000..d9076bea8 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanService.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.MesWmStockTakingPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.MesWmStockTakingPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 盘点方案 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmStockTakingPlanService { + + /** + * 创建盘点方案 + * + * @param createReqVO 创建信息 + * @return 盘点方案编号 + */ + Long createStockTakingPlan(@Valid MesWmStockTakingPlanSaveReqVO createReqVO); + + /** + * 更新盘点方案 + * + * @param updateReqVO 更新信息 + */ + void updateStockTakingPlan(@Valid MesWmStockTakingPlanSaveReqVO updateReqVO); + + /** + * 删除盘点方案 + * + * @param id 盘点方案编号 + */ + void deleteStockTakingPlan(Long id); + + /** + * 更新盘点方案状态。 + * + * @param id 盘点方案编号 + * @param status 状态 + */ + void updateStockTakingPlanStatus(Long id, Integer status); + + /** + * 获得盘点方案 + * + * @param id 盘点方案编号 + * @return 盘点方案 + */ + MesWmStockTakingPlanDO getStockTakingPlan(Long id); + + /** + * 校验盘点方案是否存在 + * + * @param id 盘点方案编号 + * @return 盘点方案 + */ + MesWmStockTakingPlanDO validateStockTakingPlanExists(Long id); + + /** + * 校验盘点方案是否可编辑 + * + * @param id 盘点方案编号 + * @return 盘点方案 + */ + MesWmStockTakingPlanDO validateStockTakingPlanEditable(Long id); + + /** + * 校验盘点方案存在且已启用 + * + * @param id 盘点方案编号 + * @return 盘点方案 + */ + MesWmStockTakingPlanDO validateStockTakingPlanEnabled(Long id); + + /** + * 获得盘点方案列表。 + * + * @param ids 盘点方案编号集合 + * @return 盘点方案列表 + */ + List getStockTakingPlanList(Collection ids); + + /** + * 获得盘点方案 Map + * + * @param ids 盘点方案编号集合 + * @return 盘点方案 Map + */ + default Map getStockTakingPlanMap(Collection ids) { + return convertMap(getStockTakingPlanList(ids), MesWmStockTakingPlanDO::getId); + } + + /** + * 分页查询盘点方案 + * + * @param pageReqVO 分页查询条件 + * @return 盘点方案分页结果 + */ + PageResult getStockTakingPlanPage(MesWmStockTakingPlanPageReqVO pageReqVO); + + /** + * 根据状态获得盘点方案列表。 + * + * @param status 状态 + * @return 盘点方案列表 + */ + List getStockTakingPlanListByStatus(Integer status); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanServiceImpl.java new file mode 100644 index 000000000..81f9589a5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanServiceImpl.java @@ -0,0 +1,173 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.MesWmStockTakingPlanPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.MesWmStockTakingPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanParamDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.plan.MesWmStockTakingPlanMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTypeEnum; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 盘点方案 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmStockTakingPlanServiceImpl implements MesWmStockTakingPlanService { + + @Resource + private MesWmStockTakingPlanMapper stockTakingPlanMapper; + @Resource + private MesWmStockTakingPlanParamService stockTakingPlanParamService; + + @Override + public Long createStockTakingPlan(MesWmStockTakingPlanSaveReqVO createReqVO) { + // 校验并处理保存数据 + validatePlanSaveData(createReqVO); + + // 插入数据 + MesWmStockTakingPlanDO plan = BeanUtils.toBean(createReqVO, MesWmStockTakingPlanDO.class); + plan.setStatus(CommonStatusEnum.DISABLE.getStatus()); + stockTakingPlanMapper.insert(plan); + return plan.getId(); + } + + @Override + public void updateStockTakingPlan(MesWmStockTakingPlanSaveReqVO updateReqVO) { + // 校验盘点方案存在,并且是可编辑状态 + validatePlanEditable(updateReqVO.getId()); + // 校验并处理保存数据 + validatePlanSaveData(updateReqVO); + + // 更新数据 + MesWmStockTakingPlanDO updateObj = BeanUtils.toBean(updateReqVO, MesWmStockTakingPlanDO.class); + stockTakingPlanMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockTakingPlan(Long id) { + // 校验盘点方案存在,并且是可编辑状态 + validatePlanEditable(id); + + // 删除盘点方案参数 + stockTakingPlanParamService.deleteStockTakingPlanParamByPlanId(id); + // 删除盘点方案 + stockTakingPlanMapper.deleteById(id); + } + + @Override + public void updateStockTakingPlanStatus(Long id, Integer status) { + // 校验盘点方案存在 + validateStockTakingPlanExists(id); + // 开启时,需要校验 params 非空 + if (CommonStatusEnum.isEnable(status)) { + List params = stockTakingPlanParamService.getStockTakingPlanParamListByPlanId(id); + if (CollUtil.isEmpty(params)) { + throw exception(WM_STOCK_TAKING_PLAN_PARAM_EMPTY); + } + } + + // 更新状态 + stockTakingPlanMapper.updateById(new MesWmStockTakingPlanDO().setId(id).setStatus(status)); + } + + @Override + public MesWmStockTakingPlanDO getStockTakingPlan(Long id) { + return stockTakingPlanMapper.selectById(id); + } + + @Override + public MesWmStockTakingPlanDO validateStockTakingPlanExists(Long id) { + MesWmStockTakingPlanDO plan = stockTakingPlanMapper.selectById(id); + if (plan == null) { + throw exception(WM_STOCK_TAKING_PLAN_NOT_EXISTS); + } + return plan; + } + + @Override + public MesWmStockTakingPlanDO validateStockTakingPlanEditable(Long id) { + return validatePlanEditable(id); + } + + @Override + public List getStockTakingPlanList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return stockTakingPlanMapper.selectByIds(ids); + } + + @Override + public PageResult getStockTakingPlanPage(MesWmStockTakingPlanPageReqVO pageReqVO) { + return stockTakingPlanMapper.selectPage(pageReqVO); + } + + @Override + public List getStockTakingPlanListByStatus(Integer status) { + return stockTakingPlanMapper.selectListByStatus(status); + } + + private void validatePlanCodeUnique(Long id, String code) { + MesWmStockTakingPlanDO plan = stockTakingPlanMapper.selectByCode(code); + if (plan == null) { + return; + } + if (ObjUtil.notEqual(plan.getId(), id)) { + throw exception(WM_STOCK_TAKING_PLAN_CODE_DUPLICATE); + } + } + + @Override + public MesWmStockTakingPlanDO validateStockTakingPlanEnabled(Long id) { + MesWmStockTakingPlanDO plan = validateStockTakingPlanExists(id); + if (!CommonStatusEnum.isEnable(plan.getStatus())) { + throw exception(WM_STOCK_TAKING_PLAN_NOT_ENABLED); + } + return plan; + } + + private MesWmStockTakingPlanDO validatePlanEditable(Long id) { + MesWmStockTakingPlanDO plan = validateStockTakingPlanExists(id); + if (!CommonStatusEnum.isDisable(plan.getStatus())) { + throw exception(WM_STOCK_TAKING_PLAN_NOT_DISABLED); + } + return plan; + } + + private void validatePlanSaveData(MesWmStockTakingPlanSaveReqVO saveReqVO) { + // 校验 code 的唯一性 + validatePlanCodeUnique(saveReqVO.getId(), saveReqVO.getCode()); + + // 校验/处理动态盘点时间 + if (ObjUtil.notEqual(MesWmStockTakingTypeEnum.DYNAMIC.getType(), saveReqVO.getType())) { + // 非动态盘点类型清空时间字段 + saveReqVO.setStartTime(null); + saveReqVO.setEndTime(null); + } else { + if (saveReqVO.getStartTime() == null || saveReqVO.getEndTime() == null + || saveReqVO.getStartTime().compareTo(saveReqVO.getEndTime()) >= 0) { + throw exception(WM_STOCK_TAKING_PLAN_DYNAMIC_TIME_INVALID); + } + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskLineService.java new file mode 100644 index 000000000..353237afb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskLineService.java @@ -0,0 +1,117 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line.MesWmStockTakingTaskLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line.MesWmStockTakingTaskLineSaveReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskLineDO; + +import java.math.BigDecimal; +import java.util.List; + +/** + * MES 盘点任务行 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmStockTakingTaskLineService { + + /** + * 根据盘点方案生成盘点明细行 + * + * @param task 盘点任务 + * @param isCreate 是否为创建操作(true-创建,false-更新时需先清理旧数据) + */ + void generateStockTakingLines(MesWmStockTakingTaskDO task, boolean isCreate); + + /** + * 分页查询盘点任务行 + * + * @param pageReqVO 分页查询条件 + * @return 盘点任务行分页结果 + */ + PageResult getStockTakingTaskLinePage(MesWmStockTakingTaskLinePageReqVO pageReqVO); + + /** + * 获得盘点任务行 + * + * @param id 编号 + * @return 盘点任务行 + */ + MesWmStockTakingTaskLineDO getStockTakingTaskLine(Long id); + + /** + * 创建盘点任务行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockTakingTaskLine(MesWmStockTakingTaskLineSaveReqVO createReqVO); + + /** + * 更新盘点任务行 + * + * @param updateReqVO 更新信息 + */ + void updateStockTakingTaskLine(MesWmStockTakingTaskLineSaveReqVO updateReqVO); + + /** + * 删除盘点任务行 + * + * @param id 盘点任务行编号 + */ + void deleteStockTakingTaskLine(Long id); + + /** + * 根据任务编号获取盘点任务行列表 + * + * @param taskId 任务编号 + * @return 盘点任务行列表 + */ + List getStockTakingTaskLineListByTaskId(Long taskId); + + /** + * 根据任务编号删除盘点任务行 + * + * @param taskId 任务编号 + */ + void deleteStockTakingTaskLineByTaskId(Long taskId); + + /** + * 从盘点结果创建盘点任务行 + * + * 注意:当盘点结果没有对应的盘点清单行时,会自动创建一个新的盘点任务行 + * + * @param createReqVO 盘点结果创建信息 + * @return 盘点任务行编号 + */ + Long createStockTakingTaskLine(MesWmStockTakingTaskResultSaveReqVO createReqVO); + + /** + * 根据 taskId + itemId + areaId 查询盘点任务行 + * + * @param taskId 盘点任务编号 + * @param itemId 物料编号 + * @param areaId 库位编号 + * @return 盘点任务行 + */ + MesWmStockTakingTaskLineDO getStockTakingTaskLine(Long taskId, Long itemId, Long areaId); + + /** + * 校验盘点任务行存在 + * + * @param id 盘点任务行编号 + * @return 盘点任务行 + */ + MesWmStockTakingTaskLineDO validateStockTakingTaskLineExists(Long id); + + /** + * 更新盘点任务行的盘点数量 + * + * @param id 盘点任务行编号 + * @param takingQuantity 盘点数量(增量) + */ + void updateStockTakingTaskLineTakingQuantity(Long id, BigDecimal takingQuantity); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskLineServiceImpl.java new file mode 100644 index 000000000..a0ca107c2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskLineServiceImpl.java @@ -0,0 +1,232 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.task; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line.MesWmStockTakingTaskLinePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.line.MesWmStockTakingTaskLineSaveReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanParamDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.task.MesWmStockTakingTaskLineMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingPlanParamTypeEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTaskLineStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTypeEnum; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan.MesWmStockTakingPlanParamService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_STOCK_TAKING_TASK_LINE_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_STOCK_TAKING_TASK_NO_STOCK; + +/** + * MES 盘点任务行 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmStockTakingTaskLineServiceImpl implements MesWmStockTakingTaskLineService { + + @Resource + private MesWmStockTakingTaskLineMapper stockTakingTaskLineMapper; + @Resource + private MesWmStockTakingPlanParamService stockTakingPlanParamService; + @Resource + private MesWmMaterialStockService materialStockService; + @Resource + private MesWmStockTakingTaskService stockTakingTaskService; + + @Override + @Transactional(rollbackFor = Exception.class) + public void generateStockTakingLines(MesWmStockTakingTaskDO task, boolean isCreate) { + // 1. 如果非创建操作,先清理旧数据 + if (!isCreate) { + stockTakingTaskLineMapper.deleteByTaskId(task.getId()); + } + + // 2.1 构建查询条件(包含动态盘点时间校验) + MesWmMaterialStockListReqVO reqVO = buildStockQueryReqVO(task); + // 2.2 查询物料库存 + List stocks = materialStockService.getMaterialStockList(reqVO); + if (CollUtil.isEmpty(stocks)) { + throw exception(WM_STOCK_TAKING_TASK_NO_STOCK); + } + + // 3. 批量生成明细行 + List lines = convertList(stocks, stock -> MesWmStockTakingTaskLineDO.builder() + .taskId(task.getId()).materialStockId(stock.getId()).itemId(stock.getItemId()) + .batchId(stock.getBatchId()).quantity(stock.getQuantity()).takingQuantity(BigDecimal.ZERO) + .warehouseId(stock.getWarehouseId()).locationId(stock.getLocationId()).areaId(stock.getAreaId()) + .status(MesWmStockTakingTaskLineStatusEnum.LOSS.getStatus()).build()); + stockTakingTaskLineMapper.insertBatch(lines); + } + + @Override + public PageResult getStockTakingTaskLinePage(MesWmStockTakingTaskLinePageReqVO pageReqVO) { + return stockTakingTaskLineMapper.selectPage(pageReqVO); + } + + @Override + public MesWmStockTakingTaskLineDO getStockTakingTaskLine(Long id) { + return stockTakingTaskLineMapper.selectById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockTakingTaskLine(MesWmStockTakingTaskLineSaveReqVO createReqVO) { + // 1. 校验盘点任务存在,并且处于【准备中】状态 + stockTakingTaskService.validateStockTakingTaskExistsAndPrepare(createReqVO.getTaskId()); + + // 2. 创建盘点任务行 + MesWmStockTakingTaskLineDO line = BeanUtils.toBean(createReqVO, MesWmStockTakingTaskLineDO.class); + line.setStatus(MesWmStockTakingTaskLineStatusEnum.LOSS.getStatus()); // 默认状态:盘亏(与 generateStockTakingLines 保持一致,待盘点后由 calculateLineStatus 更新) + stockTakingTaskLineMapper.insert(line); + return line.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockTakingTaskLine(MesWmStockTakingTaskLineSaveReqVO updateReqVO) { + // 1.1 校验盘点任务行存在 + MesWmStockTakingTaskLineDO line = validateStockTakingTaskLineExists(updateReqVO.getId()); + // 1.2 校验盘点任务存在,并且处于【准备中】状态 + stockTakingTaskService.validateStockTakingTaskExistsAndPrepare(updateReqVO.getTaskId()); + + // 2. 更新盘点任务行 + MesWmStockTakingTaskLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmStockTakingTaskLineDO.class); + stockTakingTaskLineMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockTakingTaskLine(Long id) { + // 1.1 校验盘点任务行存在 + MesWmStockTakingTaskLineDO line = validateStockTakingTaskLineExists(id); + // 1.2 校验盘点任务存在,并且处于【准备中】状态 + stockTakingTaskService.validateStockTakingTaskExistsAndPrepare(line.getTaskId()); + + // 2. 删除盘点任务行 + stockTakingTaskLineMapper.deleteById(id); + } + + @Override + public MesWmStockTakingTaskLineDO validateStockTakingTaskLineExists(Long id) { + MesWmStockTakingTaskLineDO line = stockTakingTaskLineMapper.selectById(id); + if (line == null) { + throw exception(WM_STOCK_TAKING_TASK_LINE_NOT_EXISTS); + } + return line; + } + + /** + * 构建库存查询条件 + * + * @param task 盘点任务 + * @return 查询条件 VO + */ + private MesWmMaterialStockListReqVO buildStockQueryReqVO(MesWmStockTakingTaskDO task) { + // 1. 从方案参数中提取过滤条件 + List params = stockTakingPlanParamService.getStockTakingPlanParamListByPlanId(task.getPlanId()); + Assert.notEmpty(params, "盘点方案参数不能为空"); + + // 2.1 拼接通用参数 + MesWmMaterialStockListReqVO reqVO = new MesWmMaterialStockListReqVO() + .setWarehouseId(extractMesWmStockTakingPlanParamValueId(params, MesWmStockTakingPlanParamTypeEnum.WAREHOUSE.getType())) + .setLocationId(extractMesWmStockTakingPlanParamValueId(params, MesWmStockTakingPlanParamTypeEnum.LOCATION.getType())) + .setAreaId(extractMesWmStockTakingPlanParamValueId(params, MesWmStockTakingPlanParamTypeEnum.AREA.getType())) + .setItemId(extractMesWmStockTakingPlanParamValueId(params, MesWmStockTakingPlanParamTypeEnum.ITEM.getType())) + .setBatchId(extractMesWmStockTakingPlanParamValueId(params, MesWmStockTakingPlanParamTypeEnum.BATCH.getType())); + // 2.2 对于动态盘点,设置时间参数并校验 + if (MesWmStockTakingTypeEnum.DYNAMIC.getType().equals(task.getType())) { + Assert.notNull(task.getStartTime(), "动态盘点开始时间不能为空"); + Assert.notNull(task.getEndTime(), "动态盘点结束时间不能为空"); + reqVO.setStartTime(task.getStartTime()).setEndTime(task.getEndTime()); + } + return reqVO; + } + + @Override + public List getStockTakingTaskLineListByTaskId(Long taskId) { + return stockTakingTaskLineMapper.selectListByTaskId(taskId); + } + + @Override + public void deleteStockTakingTaskLineByTaskId(Long taskId) { + stockTakingTaskLineMapper.deleteByTaskId(taskId); + } + + @Override + public MesWmStockTakingTaskLineDO getStockTakingTaskLine(Long taskId, Long itemId, Long areaId) { + return stockTakingTaskLineMapper.selectByTaskIdAndItemIdAndAreaId(taskId, itemId, areaId); + } + + @Override + public void updateStockTakingTaskLineTakingQuantity(Long id, BigDecimal takingQuantity) { + // 1. 校验盘点任务行存在 + MesWmStockTakingTaskLineDO line = validateStockTakingTaskLineExists(id); + // 2. 更新盘点数量和状态 + line.setTakingQuantity(takingQuantity) + .setStatus(calculateLineStatus(line.getQuantity(), takingQuantity)); + stockTakingTaskLineMapper.updateById(line); + } + + @Override + public Long createStockTakingTaskLine(MesWmStockTakingTaskResultSaveReqVO createReqVO) { + MesWmStockTakingTaskLineDO line = new MesWmStockTakingTaskLineDO() + .setTaskId(createReqVO.getTaskId()).setItemId(createReqVO.getItemId()).setBatchId(createReqVO.getBatchId()) + .setWarehouseId(createReqVO.getWarehouseId()).setLocationId(createReqVO.getLocationId()).setAreaId(createReqVO.getAreaId()) + .setQuantity(BigDecimal.ZERO) // 账面数量默认为 0 + .setTakingQuantity(createReqVO.getTakingQuantity()) // 盘点数量 + .setStatus(calculateLineStatus(BigDecimal.ZERO, createReqVO.getTakingQuantity())); // 计算盈亏状态 + stockTakingTaskLineMapper.insert(line); + return line.getId(); + } + + /** + * 计算盘点任务行状态 + * + * @param quantity 账面数量 + * @param takingQuantity 盘点数量 + * @return 状态 + */ + private Integer calculateLineStatus(BigDecimal quantity, BigDecimal takingQuantity) { + Assert.notNull(takingQuantity, "盘点数量不能为空"); + Assert.notNull(quantity, "账面数量不能为空"); + int compareResult = takingQuantity.compareTo(quantity); + if (compareResult > 0) { + return MesWmStockTakingTaskLineStatusEnum.GAIN.getStatus(); // 盘盈 + } + if (compareResult < 0) { + return MesWmStockTakingTaskLineStatusEnum.LOSS.getStatus(); // 盘亏 + } + return MesWmStockTakingTaskLineStatusEnum.NORMAL.getStatus(); // 正常 + } + + /** + * 从参数列表中提取第一个匹配类型的参数 ID + * + * @param params 参数列表 + * @param type 参数类型 + * @return 参数 ID(如果有多个,取第一个) + */ + private Long extractMesWmStockTakingPlanParamValueId(List params, Integer type) { + MesWmStockTakingPlanParamDO param = CollUtil.findOne(params, + item -> Objects.equals(item.getType(), type) && item.getValueId() != null); + return param != null ? param.getValueId() : null; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskResultService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskResultService.java new file mode 100644 index 000000000..6c2ebc16b --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskResultService.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskResultDO; + +/** + * MES 盘点结果 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmStockTakingTaskResultService { + + /** + * 分页查询盘点结果 + * + * @param pageReqVO 分页查询条件 + * @return 盘点结果分页结果 + */ + PageResult getStockTakingTaskResultPage(MesWmStockTakingTaskResultPageReqVO pageReqVO); + + /** + * 获得盘点结果 + * + * @param id 盘点结果编号 + * @return 盘点结果 + */ + MesWmStockTakingTaskResultDO getStockTakingTaskResult(Long id); + + /** + * 创建盘点结果 + * + * @param result 盘点结果 + * @return 盘点结果编号 + */ + Long createStockTakingTaskResult(MesWmStockTakingTaskResultSaveReqVO result); + + /** + * 更新盘点结果 + * + * @param result 盘点结果 + */ + void updateStockTakingTaskResult(MesWmStockTakingTaskResultSaveReqVO result); + + /** + * 删除盘点结果 + * + * @param id 盘点结果编号 + */ + void deleteStockTakingTaskResult(Long id); + + /** + * 根据任务编号删除盘点结果 + * + * @param taskId 任务编号 + */ + void deleteStockTakingTaskResultByTaskId(Long taskId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskResultServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskResultServiceImpl.java new file mode 100644 index 000000000..2315426ee --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskResultServiceImpl.java @@ -0,0 +1,143 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.task; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result.MesWmStockTakingTaskResultSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskResultDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.task.MesWmStockTakingTaskResultMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_STOCK_TAKING_TASK_LINE_ALREADY_TAKEN; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_STOCK_TAKING_TASK_RESULT_NOT_EXISTS; + +/** + * MES 盘点结果 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmStockTakingTaskResultServiceImpl implements MesWmStockTakingTaskResultService { + + @Resource + private MesWmStockTakingTaskResultMapper stockTakingTaskResultMapper; + + @Resource + private MesWmStockTakingTaskLineService stockTakingTaskLineService; + @Resource + private MesWmStockTakingTaskService stockTakingTaskService; + + @Override + public PageResult getStockTakingTaskResultPage( + MesWmStockTakingTaskResultPageReqVO pageReqVO) { + return stockTakingTaskResultMapper.selectPage(pageReqVO); + } + + @Override + public MesWmStockTakingTaskResultDO getStockTakingTaskResult(Long id) { + return stockTakingTaskResultMapper.selectById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockTakingTaskResult(MesWmStockTakingTaskResultSaveReqVO createReqVO) { + // 1. 校验任务处于盘点中状态 + stockTakingTaskService.validateStockTakingTaskExistsAndApproving(createReqVO.getTaskId()); + + // 2. 确定 lineId 和账面数量 + Long lineId = createReqVO.getLineId(); + MesWmStockTakingTaskLineDO existingLine = null; + if (lineId == null) { + // 2.1 基于 taskId + itemId + areaId 查询已存在的 line + existingLine = stockTakingTaskLineService.getStockTakingTaskLine( + createReqVO.getTaskId(), createReqVO.getItemId(), createReqVO.getAreaId()); + if (existingLine != null) { + lineId = existingLine.getId(); + } else { + // 2.2 创建新的 line(注意:当盘点结果没有对应的盘点清单行时,会自动创建一个新的盘点任务行) + lineId = stockTakingTaskLineService.createStockTakingTaskLine(createReqVO); + } + } else { + // 2.3 如果传递了 lineId,从 line 中获取 quantity + existingLine = stockTakingTaskLineService.validateStockTakingTaskLineExists(lineId); + } + if (existingLine != null + && existingLine.getTakingQuantity() != null + && existingLine.getTakingQuantity().compareTo(BigDecimal.ZERO) > 0) { + throw exception(WM_STOCK_TAKING_TASK_LINE_ALREADY_TAKEN); + } + BigDecimal quantity = existingLine != null ? existingLine.getQuantity() : BigDecimal.ZERO; // 账面数量 + + // 3. 插入 result 记录 + MesWmStockTakingTaskResultDO result = BeanUtils.toBean(createReqVO, MesWmStockTakingTaskResultDO.class) + .setLineId(lineId).setQuantity(ObjUtil.defaultIfNull(quantity, createReqVO.getTakingQuantity())); + stockTakingTaskResultMapper.insert(result); + + // 4. 更新 line 的盘点数量和状态 + stockTakingTaskLineService.updateStockTakingTaskLineTakingQuantity(lineId, createReqVO.getTakingQuantity()); + return result.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockTakingTaskResult(MesWmStockTakingTaskResultSaveReqVO updateReqVO) { + updateReqVO.setLineId(null); // lineId 不能修改,避免误操作 + // 1.1 校验记录存在 + MesWmStockTakingTaskResultDO oldResult = validateStockTakingTaskResultExists(updateReqVO.getId()); + // 1.2 校验任务处于盘点中状态 + stockTakingTaskService.validateStockTakingTaskExistsAndApproving(oldResult.getTaskId()); + + // 2. 更新 result 记录 + MesWmStockTakingTaskResultDO result = BeanUtils.toBean(updateReqVO, MesWmStockTakingTaskResultDO.class); + stockTakingTaskResultMapper.updateById(result); + + // 3. 关联更新 line 的盘点数量(覆盖式更新) + stockTakingTaskLineService.updateStockTakingTaskLineTakingQuantity( + oldResult.getLineId(), updateReqVO.getTakingQuantity()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockTakingTaskResult(Long id) { + // 1.1 校验 result 是否存在 + MesWmStockTakingTaskResultDO result = validateStockTakingTaskResultExists(id); + // 1.2 校验 task 是否处于 APPROVING 状态 + stockTakingTaskService.validateStockTakingTaskExistsAndApproving(result.getTaskId()); + + // 2. 删除 result 记录 + stockTakingTaskResultMapper.deleteById(id); + + // 3. 更新对应 line 的盘点数量和状态 + stockTakingTaskLineService.updateStockTakingTaskLineTakingQuantity( + result.getLineId(), result.getTakingQuantity().negate()); + } + + @Override + public void deleteStockTakingTaskResultByTaskId(Long taskId) { + stockTakingTaskResultMapper.deleteByTaskId(taskId); + } + + /** + * 校验盘点结果是否存在 + * + * @param id 盘点结果编号 + * @return 盘点结果 + */ + private MesWmStockTakingTaskResultDO validateStockTakingTaskResultExists(Long id) { + MesWmStockTakingTaskResultDO result = stockTakingTaskResultMapper.selectById(id); + if (result == null) { + throw exception(WM_STOCK_TAKING_TASK_RESULT_NOT_EXISTS); + } + return result; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskService.java new file mode 100644 index 000000000..f5202e434 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskService.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.task; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.MesWmStockTakingTaskPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.MesWmStockTakingTaskSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskDO; +import jakarta.validation.Valid; + +/** + * MES 盘点任务 Service 接口 + * + * @author 芋道源码 + */ +public interface MesWmStockTakingTaskService { + + /** + * 创建盘点任务 + * + * @param createReqVO 创建信息 + * @return 盘点任务编号 + */ + Long createStockTakingTask(@Valid MesWmStockTakingTaskSaveReqVO createReqVO); + + /** + * 更新盘点任务 + * + * @param updateReqVO 更新信息 + */ + void updateStockTakingTask(@Valid MesWmStockTakingTaskSaveReqVO updateReqVO); + + /** + * 删除盘点任务 + * + * @param id 盘点任务编号 + */ + void deleteStockTakingTask(Long id); + + /** + * 提交盘点任务 + * + * @param id 盘点任务编号 + */ + void submitStockTakingTask(Long id); + + /** + * 完成盘点任务 + * + * @param id 盘点任务编号 + */ + void finishStockTakingTask(Long id); + + /** + * 取消盘点任务 + * + * @param id 盘点任务编号 + */ + void cancelStockTakingTask(Long id); + + /** + * 获得盘点任务 + * + * @param id 盘点任务编号 + * @return 盘点任务 + */ + MesWmStockTakingTaskDO getStockTakingTask(Long id); + + /** + * 校验盘点任务是否存在 + * + * @param id 盘点任务编号 + * @return 盘点任务 + */ + MesWmStockTakingTaskDO validateStockTakingTaskExists(Long id); + + /** + * 校验盘点任务存在,并且处于【准备中】状态 + * + * @param id 盘点任务编号 + * @return 盘点任务 + */ + MesWmStockTakingTaskDO validateStockTakingTaskExistsAndPrepare(Long id); + + /** + * 校验盘点任务存在,并且处于【盘点中】状态 + * + * @param id 盘点任务编号 + * @return 盘点任务 + */ + MesWmStockTakingTaskDO validateStockTakingTaskExistsAndApproving(Long id); + + /** + * 分页查询盘点任务 + * + * @param pageReqVO 分页查询条件 + * @return 盘点任务分页结果 + */ + PageResult getStockTakingTaskPage(MesWmStockTakingTaskPageReqVO pageReqVO); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java new file mode 100644 index 000000000..efaf298a7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/task/MesWmStockTakingTaskServiceImpl.java @@ -0,0 +1,223 @@ +package cn.iocoder.yudao.module.mes.service.wm.stocktaking.task; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.MesWmStockTakingTaskPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.MesWmStockTakingTaskSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.task.MesWmStockTakingTaskLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.stocktaking.task.MesWmStockTakingTaskMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmStockTakingTaskStatusEnum; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.stocktaking.plan.MesWmStockTakingPlanService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 盘点任务 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesWmStockTakingTaskServiceImpl implements MesWmStockTakingTaskService { + + @Resource + private MesWmStockTakingTaskMapper stockTakingTaskMapper; + + @Resource + private MesWmMaterialStockService materialStockService; + @Resource + private MesWmStockTakingPlanService stockTakingPlanService; + @Lazy + @Resource + private MesWmStockTakingTaskLineService stockTakingTaskLineService; + @Lazy + @Resource + private MesWmStockTakingTaskResultService stockTakingTaskResultService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockTakingTask(MesWmStockTakingTaskSaveReqVO createReqVO) { + // 1.1 校验 code 唯一 + validateStockTakingTaskCodeUnique(null, createReqVO.getCode()); + // 1.2 校验方案存在 + adminUserApi.validateUser(createReqVO.getUserId()); + // 1.3 校验方案可用(如果有 planId) + if (createReqVO.getPlanId() != null) { + stockTakingPlanService.validateStockTakingPlanEnabled(createReqVO.getPlanId()); + } + + // 2. 插入任务 + MesWmStockTakingTaskDO task = BeanUtils.toBean(createReqVO, MesWmStockTakingTaskDO.class) + .setStatus(MesWmStockTakingTaskStatusEnum.PREPARE.getStatus()); + stockTakingTaskMapper.insert(task); + + // 3. 根据方案生成盘点明细行(仅当有 plan 时) + if (task.getPlanId() != null) { + stockTakingTaskLineService.generateStockTakingLines(task, true); + } + return task.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockTakingTask(MesWmStockTakingTaskSaveReqVO updateReqVO) { + // 1.1 校验任务存在且为草稿状态 + validateStockTakingTaskExistsAndPrepare(updateReqVO.getId()); + // 1.2 校验 code 唯一 + validateStockTakingTaskCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + // 1.3 校验方案存在 + adminUserApi.validateUser(updateReqVO.getUserId()); + // 1.4 校验方案可用(如果有 planId) + if (updateReqVO.getPlanId() != null) { + stockTakingPlanService.validateStockTakingPlanEnabled(updateReqVO.getPlanId()); + } + + // 2. 更新任务 + MesWmStockTakingTaskDO updateObj = BeanUtils.toBean(updateReqVO, MesWmStockTakingTaskDO.class); + stockTakingTaskMapper.updateById(updateObj); + + // 3. 重新生成盘点明细行(仅当有 plan 时) + if (updateObj.getPlanId() != null) { + stockTakingTaskLineService.generateStockTakingLines(updateObj, false); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockTakingTask(Long id) { + // 1. 校验任务存在且为草稿状态 + validateStockTakingTaskExistsAndPrepare(id); + + // 2. 删除任务和明细 + stockTakingTaskResultService.deleteStockTakingTaskResultByTaskId(id); + stockTakingTaskLineService.deleteStockTakingTaskLineByTaskId(id); + stockTakingTaskMapper.deleteById(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitStockTakingTask(Long id) { + // 1.1 校验任务存在且为草稿状态 + MesWmStockTakingTaskDO task = validateStockTakingTaskExistsAndPrepare(id); + // 1.2 检查要盘点的内容 + List lines = stockTakingTaskLineService.getStockTakingTaskLineListByTaskId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_STOCK_TAKING_TASK_NO_LINE); + } + + // 2. 更新任务状态为审批中 + stockTakingTaskMapper.updateById(new MesWmStockTakingTaskDO().setId(id) + .setStatus(MesWmStockTakingTaskStatusEnum.APPROVING.getStatus())); + + // 3. 根据冻结标识,对物资进行冻结 + if (Boolean.TRUE.equals(task.getFrozen())) { + updateMaterialStockFrozen(lines, true); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishStockTakingTask(Long id) { + // 1. 校验任务存在且为审批中状态 + MesWmStockTakingTaskDO task = validateStockTakingTaskExistsAndApproving(id); + + // 2. 更新任务状态为已完成 + stockTakingTaskMapper.updateById(new MesWmStockTakingTaskDO().setId(id) + .setStatus(MesWmStockTakingTaskStatusEnum.FINISHED.getStatus())); + + // 3. 解冻库存 + if (Boolean.TRUE.equals(task.getFrozen())) { + List lines = stockTakingTaskLineService.getStockTakingTaskLineListByTaskId(id); + updateMaterialStockFrozen(lines, false); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelStockTakingTask(Long id) { + MesWmStockTakingTaskDO task = validateStockTakingTaskExists(id); + if (MesWmStockTakingTaskStatusEnum.FINISHED.getStatus().equals(task.getStatus()) + || MesWmStockTakingTaskStatusEnum.CANCELED.getStatus().equals(task.getStatus())) { + throw exception(WM_STOCK_TAKING_TASK_CANNOT_CANCEL); + } + task.setStatus(MesWmStockTakingTaskStatusEnum.CANCELED.getStatus()); + stockTakingTaskMapper.updateById(task); + if (Boolean.TRUE.equals(task.getFrozen())) { + updateMaterialStockFrozen(stockTakingTaskLineService.getStockTakingTaskLineListByTaskId(id), false); + } + } + + @Override + public MesWmStockTakingTaskDO getStockTakingTask(Long id) { + return stockTakingTaskMapper.selectById(id); + } + + @Override + public MesWmStockTakingTaskDO validateStockTakingTaskExists(Long id) { + MesWmStockTakingTaskDO task = stockTakingTaskMapper.selectById(id); + if (task == null) { + throw exception(WM_STOCK_TAKING_TASK_NOT_EXISTS); + } + return task; + } + + @Override + public MesWmStockTakingTaskDO validateStockTakingTaskExistsAndPrepare(Long id) { + MesWmStockTakingTaskDO task = validateStockTakingTaskExists(id); + if (ObjUtil.notEqual(MesWmStockTakingTaskStatusEnum.PREPARE.getStatus(), task.getStatus())) { + throw exception(WM_STOCK_TAKING_TASK_NOT_PREPARE); + } + return task; + } + + @Override + public MesWmStockTakingTaskDO validateStockTakingTaskExistsAndApproving(Long id) { + MesWmStockTakingTaskDO task = validateStockTakingTaskExists(id); + if (ObjUtil.notEqual(MesWmStockTakingTaskStatusEnum.APPROVING.getStatus(), task.getStatus())) { + throw exception(WM_STOCK_TAKING_TASK_NOT_APPROVING); + } + return task; + } + + @Override + public PageResult getStockTakingTaskPage(MesWmStockTakingTaskPageReqVO pageReqVO) { + return stockTakingTaskMapper.selectPage(pageReqVO); + } + + private void updateMaterialStockFrozen(List lines, boolean frozen) { + if (CollUtil.isEmpty(lines)) { + return; + } + List materialStockIds = convertList(lines, + MesWmStockTakingTaskLineDO::getMaterialStockId, line -> line.getMaterialStockId() != null); + materialStockService.updateMaterialStockFrozen(materialStockIds, frozen); + } + + private void validateStockTakingTaskCodeUnique(Long id, String code) { + MesWmStockTakingTaskDO task = stockTakingTaskMapper.selectByCode(code); + if (task == null) { + return; + } + if (ObjUtil.notEqual(task.getId(), id)) { + throw exception(WM_STOCK_TAKING_TASK_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/MesWmTransactionService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/MesWmTransactionService.java new file mode 100644 index 000000000..472f1e6f9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/MesWmTransactionService.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.service.wm.transaction; + +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 库存事务流水 Service 接口 + * + * 校验 → 库存台账更新 → 事务流水插入。 + */ +public interface MesWmTransactionService { + + /** + * 创建库存事务(含校验 + 库存更新 + 插入流水) + * + * @param reqDTO 事务数据 + * @return 事务流水编号 + */ + Long createTransaction(@Valid MesWmTransactionSaveReqDTO reqDTO); + + /** + * 批量创建库存事务 + * + * @param reqDTOs 事务数据列表 + */ + void createTransactionList(List reqDTOs); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/MesWmTransactionServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/MesWmTransactionServiceImpl.java new file mode 100644 index 000000000..a967b8905 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/MesWmTransactionServiceImpl.java @@ -0,0 +1,197 @@ +package cn.iocoder.yudao.module.mes.service.wm.transaction; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transaction.MesWmTransactionDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.transaction.MesWmTransactionMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 库存事务流水 Service 实现类 + */ +@Service +@Validated +public class MesWmTransactionServiceImpl implements MesWmTransactionService { + + @Resource + private MesWmTransactionMapper transactionMapper; + @Resource + private MesWmMaterialStockService materialStockService; + @Resource + private MesWmBatchService batchService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmWarehouseService warehouseService; + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmWarehouseAreaService areaService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createTransaction(MesWmTransactionSaveReqDTO reqDTO) { + // 1.1 校验事务类型 + MesWmTransactionTypeEnum typeEnum = MesWmTransactionTypeEnum.valueOf(reqDTO.getType()); + if (typeEnum == null) { + throw exception(WM_TRANSACTION_TYPE_NOT_EXISTS); + } + // 1.2 校验 quantity 正负号与事务方向一致(入库必须正数,出库必须负数) + boolean inbound = typeEnum.isInbound(); + checkQuantity(reqDTO, inbound); + // 1.3 入库事务:批次号校验 + batchId/batchCode 互补 + checkBatch(reqDTO, inbound); + // 1.4 入库事务:库位混放规则校验 + if (inbound) { + materialStockService.checkAreaMixingRule(reqDTO.getAreaId(), reqDTO.getItemId(), reqDTO.getBatchId()); + } + // 1.5 关联事务校验 + checkRelatedTransaction(reqDTO); + + // 2.1 获取或创建库存记录 + MesWmMaterialStockDO materialStock = materialStockService.getOrCreateMaterialStock( + reqDTO.getItemId(), reqDTO.getWarehouseId(), reqDTO.getLocationId(), reqDTO.getAreaId(), + reqDTO.getBatchId(), reqDTO.getBatchCode(), reqDTO.getVendorId(), reqDTO.getReceiptTime()); + // 2.2 冻结校验(仓库、库区、库位、库存记录) + checkFrozen(reqDTO, materialStock); + // 2.3 更新库存数量 + boolean checkFlag = ObjUtil.defaultIfNull(reqDTO.getCheckFlag(), true); + materialStockService.updateMaterialStockQuantity(materialStock.getId(), reqDTO.getQuantity(), checkFlag); + + // 3. 插入事务流水 + MesWmTransactionDO transaction = MesWmTransactionDO.builder() + .type(reqDTO.getType()).quantity(reqDTO.getQuantity()).transactionTime(LocalDateTime.now()) + .itemId(reqDTO.getItemId()).batchId(reqDTO.getBatchId()).batchCode(reqDTO.getBatchCode()) + .warehouseId(reqDTO.getWarehouseId()).locationId(reqDTO.getLocationId()).areaId(reqDTO.getAreaId()) + .bizType(reqDTO.getBizType()).bizId(reqDTO.getBizId()).bizCode(reqDTO.getBizCode()).bizLineId(reqDTO.getBizLineId()) + .materialStockId(materialStock.getId()).relatedTransactionId(reqDTO.getRelatedTransactionId()) + .build(); + transactionMapper.insert(transaction); + return transaction.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void createTransactionList(List reqDTOs) { + if (CollUtil.isEmpty(reqDTOs)) { + throw exception(WM_TRANSACTION_LIST_EMPTY); + } + reqDTOs.forEach(this::createTransaction); + } + + // ==================== 私有校验方法 ==================== + + /** + * 校验数量正负号与事务方向一致 + */ + private void checkQuantity(MesWmTransactionSaveReqDTO reqDTO, boolean inbound) { + if (inbound) { + Assert.isTrue(reqDTO.getQuantity().compareTo(BigDecimal.ZERO) > 0, + "入库事务数量必须为正数,实际值: {}", reqDTO.getQuantity()); + } else { + Assert.isTrue(reqDTO.getQuantity().compareTo(BigDecimal.ZERO) < 0, + "出库事务数量必须为负数,实际值: {}", reqDTO.getQuantity()); + } + } + + /** + * 批次校验:batchId/batchCode 互补 + 入库时批次号必填检查 + * + * @param reqDTO 事务请求 DTO + * @param inbound 是否入库 + */ + private void checkBatch(MesWmTransactionSaveReqDTO reqDTO, boolean inbound) { + // 1. batchId / batchCode 互补 + if (reqDTO.getBatchId() != null && StrUtil.isEmpty(reqDTO.getBatchCode())) { + MesWmBatchDO batch = batchService.getBatch(reqDTO.getBatchId()); + if (batch == null) { + throw exception(WM_TRANSACTION_BATCH_NOT_EXISTS); + } + reqDTO.setBatchCode(batch.getCode()); + } else if (StrUtil.isNotEmpty(reqDTO.getBatchCode()) && reqDTO.getBatchId() == null) { + MesWmBatchDO batch = batchService.getBatchByCode(reqDTO.getBatchCode()); + if (batch == null) { + throw exception(WM_TRANSACTION_BATCH_NOT_EXISTS); + } + reqDTO.setBatchId(batch.getId()); + } + // 2. 入库时:启用批次管理的物料,必须传递批次号 + if (inbound) { + MesMdItemDO item = itemService.validateItemExists(reqDTO.getItemId()); + if (Boolean.TRUE.equals(item.getBatchFlag())) { + if (StrUtil.isEmpty(reqDTO.getBatchCode()) && reqDTO.getBatchId() == null) { + throw exception(WM_TRANSACTION_BATCH_REQUIRED); + } + } + } + } + + /** + * 关联事务校验:relatedTransactionId 不为空时,关联的事务必须存在 + */ + private void checkRelatedTransaction(MesWmTransactionSaveReqDTO reqDTO) { + if (reqDTO.getRelatedTransactionId() == null) { + return; + } + MesWmTransactionDO relatedTransaction = transactionMapper.selectById(reqDTO.getRelatedTransactionId()); + if (relatedTransaction == null) { + throw exception(WM_TRANSACTION_RELATED_NOT_EXISTS); + } + } + + /** + * 冻结校验:检查仓库、库区、库位、库存记录是否被冻结 + * + * @param reqDTO 事务请求 DTO + * @param materialStock 库存记录 + */ + private void checkFrozen(MesWmTransactionSaveReqDTO reqDTO, MesWmMaterialStockDO materialStock) { + // 1.1 检查仓库冻结 + MesWmWarehouseDO warehouse = warehouseService.validateWarehouseExists(reqDTO.getWarehouseId()); + if (Boolean.TRUE.equals(warehouse.getFrozen())) { + throw exception(WM_TRANSACTION_WAREHOUSE_FROZEN, warehouse.getName()); + } + // 1.2 检查库区冻结 + MesWmWarehouseLocationDO location = locationService.validateWarehouseLocationExists(reqDTO.getLocationId()); + if (Boolean.TRUE.equals(location.getFrozen())) { + throw exception(WM_TRANSACTION_LOCATION_FROZEN, location.getName()); + } + // 1.3 检查库位冻结 + MesWmWarehouseAreaDO area = areaService.validateWarehouseAreaExists(reqDTO.getAreaId()); + if (Boolean.TRUE.equals(area.getFrozen())) { + throw exception(WM_TRANSACTION_AREA_FROZEN, area.getName()); + } + + // 2. 检查库存记录冻结 + if (Boolean.TRUE.equals(materialStock.getFrozen())) { + throw exception(WM_TRANSACTION_STOCK_FROZEN, warehouse.getName(), location.getName(), area.getName()); + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/dto/MesWmTransactionSaveReqDTO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/dto/MesWmTransactionSaveReqDTO.java new file mode 100644 index 000000000..81974d132 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transaction/dto/MesWmTransactionSaveReqDTO.java @@ -0,0 +1,116 @@ +package cn.iocoder.yudao.module.mes.service.wm.transaction.dto; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * MES 库存事务 创建 Request DTO + */ +@Data +@Accessors(chain = true) +public class MesWmTransactionSaveReqDTO { + + // ===== 事务核心 ===== + + /** + * 事务类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum} + */ + @NotNull(message = "事务类型不能为空") + private Integer type; + + // ===== 业务来源 ===== + + /** + * 业务类型 + * + * 对应 {@link cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants} + */ + @NotNull(message = "业务类型不能为空") + private Integer bizType; + /** + * 业务主单 ID + */ + @NotNull(message = "业务主单 ID 不能为空") + private Long bizId; + /** + * 业务单号 + */ + @NotNull(message = "业务单号不能为空") + private String bizCode; + /** + * 业务行 ID + */ + @NotNull(message = "业务行 ID 不能为空") + private Long bizLineId; + + // ===== 物料维度 ===== + + /** + * 物料 ID + */ + @NotNull(message = "物料 ID 不能为空") + private Long itemId; + /** + * 变动数量(入库为正数,出库为负数) + */ + @NotNull(message = "变动数量不能为空") + private BigDecimal quantity; + /** + * 批次 ID + */ + private Long batchId; + /** + * 批次号 + */ + private String batchCode; + + // ===== 库存位置 ===== + + /** + * 仓库 ID + */ + @NotNull(message = "仓库 ID 不能为空") + private Long warehouseId; + /** + * 库区 ID + */ + @NotNull(message = "库区 ID 不能为空") + private Long locationId; + /** + * 库位 ID + */ + @NotNull(message = "库位 ID 不能为空") + private Long areaId; + + // ===== 台账补充字段(入库时用于初始化 MesWmMaterialStockDO) ===== + + /** + * 供应商 ID(采购入库场景) + */ + private Long vendorId; + /** + * 入库时间(为空默认当前时间) + */ + private LocalDateTime receiptTime; + + // ===== 关联 ===== + + /** + * 关联事务 ID(成对事务中,入库事务关联出库事务) + */ + private Long relatedTransactionId; + + // ===== 可选控制(非存储字段) ===== + + /** + * 是否校验库存充足(默认 true;线边库消耗等场景设 false 允许负库存) + */ + private Boolean checkFlag; + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferDetailService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferDetailService.java new file mode 100644 index 000000000..6506bdb51 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferDetailService.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.mes.service.wm.transfer; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.detail.MesWmTransferDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDetailDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 调拨明细 Service 接口 + */ +public interface MesWmTransferDetailService { + + /** + * 创建调拨明细 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTransferDetail(@Valid MesWmTransferDetailSaveReqVO createReqVO); + + /** + * 更新调拨明细 + * + * @param updateReqVO 更新信息 + */ + void updateTransferDetail(@Valid MesWmTransferDetailSaveReqVO updateReqVO); + + /** + * 删除调拨明细 + * + * @param id 编号 + */ + void deleteTransferDetail(Long id); + + /** + * 获得调拨明细 + * + * @param id 编号 + * @return 调拨明细 + */ + MesWmTransferDetailDO getTransferDetail(Long id); + + /** + * 根据行 ID 获取明细列表 + * + * @param lineId 行 ID + * @return 明细列表 + */ + List getTransferDetailListByLineId(Long lineId); + + /** + * 根据转移单 ID 获取明细列表 + * + * @param transferId 转移单 ID + * @return 明细列表 + */ + List getTransferDetailListByTransferId(Long transferId); + + /** + * 根据转移单 ID 删除明细 + * + * @param transferId 转移单 ID + */ + void deleteTransferDetailByTransferId(Long transferId); + + /** + * 根据行 ID 删除明细 + * + * @param lineId 行 ID + */ + void deleteTransferDetailByLineId(Long lineId); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferDetailServiceImpl.java new file mode 100644 index 000000000..2e97a5909 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferDetailServiceImpl.java @@ -0,0 +1,194 @@ +package cn.iocoder.yudao.module.mes.service.wm.transfer; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.detail.MesWmTransferDetailSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.transfer.MesWmTransferDetailMapper; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_TRANSFER_DETAIL_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_TRANSFER_DETAIL_QUANTITY_EXCEED; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_TRANSFER_DETAIL_MIXED_GOODS; + +/** + * MES 调拨明细 Service 实现类 + */ +@Service +@Validated +public class MesWmTransferDetailServiceImpl implements MesWmTransferDetailService { + + @Resource + private MesWmTransferDetailMapper transferDetailMapper; + + @Resource + @Lazy + private MesWmTransferService transferService; + @Resource + @Lazy + private MesWmTransferLineService transferLineService; + + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + + @Override + public Long createTransferDetail(MesWmTransferDetailSaveReqVO createReqVO) { + // 校验 + validateDetailSaveData(createReqVO, null); + + // 插入 + MesWmTransferDetailDO detail = BeanUtils.toBean(createReqVO, MesWmTransferDetailDO.class); + transferDetailMapper.insert(detail); + return detail.getId(); + } + + @Override + public void updateTransferDetail(MesWmTransferDetailSaveReqVO updateReqVO) { + // 校验存在 + validateTransferDetailExists(updateReqVO.getId()); + // 校验 + validateDetailSaveData(updateReqVO, updateReqVO.getId()); + + // 更新 + MesWmTransferDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmTransferDetailDO.class); + transferDetailMapper.updateById(updateObj); + } + + @Override + public void deleteTransferDetail(Long id) { + // 校验存在 + MesWmTransferDetailDO detail = transferDetailMapper.selectById(id); + if (detail == null) { + throw exception(WM_TRANSFER_DETAIL_NOT_EXISTS); + } + // 校验父转移单可编辑(通过 line 找到 transfer) + MesWmTransferLineDO line = transferLineService.validateTransferLineExists(detail.getLineId()); + transferService.validateTransferEditable(line.getTransferId()); + // 删除 + transferDetailMapper.deleteById(id); + } + + @Override + public MesWmTransferDetailDO getTransferDetail(Long id) { + return transferDetailMapper.selectById(id); + } + + @Override + public List getTransferDetailListByLineId(Long lineId) { + return transferDetailMapper.selectListByLineId(lineId); + } + + @Override + public List getTransferDetailListByTransferId(Long transferId) { + return transferDetailMapper.selectListByTransferId(transferId); + } + + @Override + public void deleteTransferDetailByTransferId(Long transferId) { + transferDetailMapper.deleteByTransferId(transferId); + } + + @Override + public void deleteTransferDetailByLineId(Long lineId) { + transferDetailMapper.deleteByLineId(lineId); + } + + private void validateTransferDetailExists(Long id) { + if (transferDetailMapper.selectById(id) == null) { + throw exception(WM_TRANSFER_DETAIL_NOT_EXISTS); + } + } + + /** + * 校验明细保存数据 + * + * @param reqVO 保存请求 + * @param excludeDetailId 排除的明细 ID(更新时排除自身,新增时传 null) + */ + private void validateDetailSaveData(MesWmTransferDetailSaveReqVO reqVO, Long excludeDetailId) { + // 校验父数据存在 + MesWmTransferLineDO line = transferLineService.validateTransferLineExists(reqVO.getLineId()); + // 校验仓库、库区、库位的关联关系 + warehouseAreaService.validateWarehouseAreaExists( + reqVO.getToWarehouseId(), reqVO.getToLocationId(), reqVO.getToAreaId()); + // 校验明细总数量不超过行数量 + validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), excludeDetailId, line); + // 校验不能混货:同一个目标仓位下,不能存在不同物料的明细 + validateNoMixedGoods(reqVO.getLineId(), reqVO.getToWarehouseId(), + reqVO.getToLocationId(), reqVO.getToAreaId(), line.getItemId(), excludeDetailId); + } + + /** + * 校验明细总数量不超过行数量 + * + * @param lineId 行 ID + * @param newQuantity 本次新增/修改的数量 + * @param excludeDetailId 排除的明细 ID(更新时排除自身,新增时传 null) + * @param line 调拨单行 + */ + private void validateDetailQuantityNotExceed(Long lineId, BigDecimal newQuantity, + Long excludeDetailId, MesWmTransferLineDO line) { + // 计算已有明细总数量(排除自身) + List details = transferDetailMapper.selectListByLineId(lineId); + BigDecimal existingTotal = CollectionUtils.getSumValue(details, + detail -> excludeDetailId != null && excludeDetailId.equals(detail.getId()) + ? BigDecimal.ZERO : detail.getQuantity(), + BigDecimal::add, BigDecimal.ZERO); + // 校验:已有 + 本次 <= 行数量 + if (existingTotal.add(newQuantity).compareTo(line.getQuantity()) > 0) { + throw exception(WM_TRANSFER_DETAIL_QUANTITY_EXCEED); + } + } + + /** + * 校验不能混货:同一转移单下,同一个目标仓位(仓库+库区+库位)只能放同一个物料 + * + * @param lineId 当前行 ID(用于排除同行明细,因为同行物料相同) + * @param toWarehouseId 目标仓库 ID + * @param toLocationId 目标库区 ID + * @param toAreaId 目标库位 ID + * @param itemId 当前物料 ID + * @param excludeDetailId 排除的明细 ID(更新时排除自身) + */ + private void validateNoMixedGoods(Long lineId, Long toWarehouseId, Long toLocationId, + Long toAreaId, Long itemId, Long excludeDetailId) { + // 1. 获取当前转移单下的所有明细 + // 说明:因为无法直接从参数拿到 transferId,所以先通过 lineId 查询当前行,进而获取 transferId 和所有明细 + MesWmTransferLineDO currentLine = transferLineService.validateTransferLineExists(lineId); + List allDetails = transferDetailMapper.selectListByTransferId(currentLine.getTransferId()); + + // 2. 遍历所有明细,校验同一个目标仓位不能有不同的物料 + for (MesWmTransferDetailDO detail : allDetails) { + // 2.1 排除当前正在编辑的明细(更新时) + if (excludeDetailId != null && excludeDetailId.equals(detail.getId())) { + continue; + } + // 2.2 排除同行的明细(同行属于同一个转移单行,物料必定相同,无需校验) + if (detail.getLineId().equals(lineId)) { + continue; + } + // 2.3 目标仓位不同,则不会混货,直接跳过 + if (ObjUtil.notEqual(detail.getToWarehouseId(), toWarehouseId) + || ObjUtil.notEqual(detail.getToLocationId(), toLocationId) + || ObjUtil.notEqual(detail.getToAreaId(), toAreaId)) { + continue; + } + // 2.4 重点:如果目标仓位相同,则必须保证物料也相同 + MesWmTransferLineDO otherLine = transferLineService.validateTransferLineExists(detail.getLineId()); + if (ObjUtil.notEqual(otherLine.getItemId(), itemId)) { + throw exception(WM_TRANSFER_DETAIL_MIXED_GOODS); + } + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineService.java new file mode 100644 index 000000000..c5e8651f4 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineService.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.service.wm.transfer; + +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.line.MesWmTransferLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferLineDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 转移单行 Service 接口 + */ +public interface MesWmTransferLineService { + + /** + * 创建转移单行 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createTransferLine(@Valid MesWmTransferLineSaveReqVO createReqVO); + + /** + * 更新转移单行 + * + * @param updateReqVO 更新信息 + */ + void updateTransferLine(@Valid MesWmTransferLineSaveReqVO updateReqVO); + + /** + * 删除转移单行 + * + * @param id 编号 + */ + void deleteTransferLine(Long id); + + /** + * 获得转移单行 + * + * @param id 编号 + * @return 转移单行 + */ + MesWmTransferLineDO getTransferLine(Long id); + + /** + * 根据转移单 ID 获取行列表 + * + * @param transferId 转移单 ID + * @return 行列表 + */ + List getTransferLineListByTransferId(Long transferId); + + /** + * 根据转移单 ID 删除行 + * + * @param transferId 转移单 ID + */ + void deleteTransferLineByTransferId(Long transferId); + + /** + * 校验转移单行是否存在 + * + * @param id 编号 + * @return 转移单行 + */ + MesWmTransferLineDO validateTransferLineExists(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineServiceImpl.java new file mode 100644 index 000000000..1028839f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineServiceImpl.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.mes.service.wm.transfer; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.line.MesWmTransferLineSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.transfer.MesWmTransferLineMapper; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_MATERIAL_STOCK_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_TRANSFER_LINE_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_TRANSFER_LINE_QUANTITY_EXCEED_STOCK; + +/** + * MES 转移单行 Service 实现类 + */ +@Service +@Validated +public class MesWmTransferLineServiceImpl implements MesWmTransferLineService { + + @Resource + private MesWmTransferLineMapper transferLineMapper; + + @Resource + @Lazy + private MesWmTransferService transferService; + @Resource + @Lazy + private MesWmTransferDetailService transferDetailService; + @Resource + private MesMdItemService itemService; + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + @Resource + private MesWmMaterialStockService materialStockService; + + @Override + public Long createTransferLine(MesWmTransferLineSaveReqVO createReqVO) { + // 校验 + validateLineSaveData(createReqVO); + + // 插入 + MesWmTransferLineDO line = BeanUtils.toBean(createReqVO, MesWmTransferLineDO.class); + transferLineMapper.insert(line); + return line.getId(); + } + + @Override + public void updateTransferLine(MesWmTransferLineSaveReqVO updateReqVO) { + // 校验存在 + validateTransferLineExists(updateReqVO.getId()); + // 校验 + validateLineSaveData(updateReqVO); + + // 更新 + MesWmTransferLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmTransferLineDO.class); + transferLineMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteTransferLine(Long id) { + // 校验存在 + MesWmTransferLineDO line = validateTransferLineExists(id); + // 校验父数据可编辑 + transferService.validateTransferEditable(line.getTransferId()); + + // 级联删除该行下所有明细 + transferDetailService.deleteTransferDetailByLineId(id); + // 删除行 + transferLineMapper.deleteById(id); + } + + @Override + public MesWmTransferLineDO getTransferLine(Long id) { + return transferLineMapper.selectById(id); + } + + @Override + public List getTransferLineListByTransferId(Long transferId) { + return transferLineMapper.selectListByTransferId(transferId); + } + + @Override + public void deleteTransferLineByTransferId(Long transferId) { + transferLineMapper.deleteByTransferId(transferId); + } + + @Override + public MesWmTransferLineDO validateTransferLineExists(Long id) { + MesWmTransferLineDO line = transferLineMapper.selectById(id); + if (line == null) { + throw exception(WM_TRANSFER_LINE_NOT_EXISTS); + } + return line; + } + + private void validateLineSaveData(MesWmTransferLineSaveReqVO reqVO) { + // 校验父数据可编辑 + transferService.validateTransferEditable(reqVO.getTransferId()); + // 校验产品存在 + itemService.validateItemExists(reqVO.getItemId()); + // 校验来源仓库、库区、库位的关联关系 + warehouseAreaService.validateWarehouseAreaExists(reqVO.getFromWarehouseId(), + reqVO.getFromLocationId(), reqVO.getFromAreaId()); + // 校验库存记录存在,且转移数量不超过库存数量 + if (reqVO.getMaterialStockId() != null) { + MesWmMaterialStockDO stock = materialStockService.getMaterialStock(reqVO.getMaterialStockId()); + if (stock == null) { + throw exception(WM_MATERIAL_STOCK_NOT_EXISTS); + } + if (stock.getQuantity() != null && reqVO.getQuantity().compareTo(stock.getQuantity()) > 0) { + throw exception(WM_TRANSFER_LINE_QUANTITY_EXCEED_STOCK); + } + } + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferService.java new file mode 100644 index 000000000..801962d0a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferService.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.mes.service.wm.transfer; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.MesWmTransferPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.MesWmTransferSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDO; +import jakarta.validation.Valid; + +/** + * MES 转移单 Service 接口 + */ +public interface MesWmTransferService { + + /** + * 创建转移单 + */ + Long createTransfer(@Valid MesWmTransferSaveReqVO createReqVO); + + /** + * 修改转移单 + */ + void updateTransfer(@Valid MesWmTransferSaveReqVO updateReqVO); + + /** + * 删除转移单 + */ + void deleteTransfer(Long id); + + /** + * 获得转移单 + */ + MesWmTransferDO getTransfer(Long id); + + /** + * 获得转移单分页 + */ + PageResult getTransferPage(MesWmTransferPageReqVO pageReqVO); + + /** + * 提交转移单(草稿 → 待确认/待上架) + */ + void submitTransfer(Long id); + + /** + * 确认转移单(待确认 → 待上架) + */ + void confirmTransfer(Long id); + + /** + * 执行上架(待上架 → 待执行) + */ + void stockTransfer(Long id); + + /** + * 完成转移单(待执行 → 已完成) + */ + void finishTransfer(Long id); + + /** + * 取消转移单 + */ + void cancelTransfer(Long id); + + /** + * 校验转移单存在且处于可编辑状态 + */ + MesWmTransferDO validateTransferEditable(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferServiceImpl.java new file mode 100644 index 000000000..9edc490d7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferServiceImpl.java @@ -0,0 +1,323 @@ +package cn.iocoder.yudao.module.mes.service.wm.transfer; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.MesWmTransferPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo.MesWmTransferSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.transfer.MesWmTransferLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.transfer.MesWmTransferMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransferStatusEnum; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 转移单 Service 实现类 + */ +@Service +@Validated +public class MesWmTransferServiceImpl implements MesWmTransferService { + + @Resource + private MesWmTransferMapper transferMapper; + + @Resource + private MesWmTransferLineService transferLineService; + @Resource + private MesWmTransferDetailService transferDetailService; + @Resource + private MesWmMaterialStockService materialStockService; + @Resource + private MesWmTransactionService wmTransactionService; + + @Override + public Long createTransfer(MesWmTransferSaveReqVO createReqVO) { + // 校验编码唯一 + validateCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesWmTransferDO transfer = BeanUtils.toBean(createReqVO, MesWmTransferDO.class); + transfer.setStatus(MesWmTransferStatusEnum.PREPARE.getStatus()); + transferMapper.insert(transfer); + return transfer.getId(); + } + + @Override + public void updateTransfer(MesWmTransferSaveReqVO updateReqVO) { + // 校验存在 + 草稿状态 + validateTransferExistsAndDraft(updateReqVO.getId()); + // 校验编码唯一 + validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesWmTransferDO updateObj = BeanUtils.toBean(updateReqVO, MesWmTransferDO.class); + transferMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteTransfer(Long id) { + // 校验存在 + 草稿状态 + validateTransferExistsAndDraft(id); + + // 级联删除明细和行 + transferDetailService.deleteTransferDetailByTransferId(id); + transferLineService.deleteTransferLineByTransferId(id); + // 删除 + transferMapper.deleteById(id); + } + + @Override + public MesWmTransferDO getTransfer(Long id) { + return transferMapper.selectById(id); + } + + @Override + public PageResult getTransferPage(MesWmTransferPageReqVO pageReqVO) { + return transferMapper.selectPage(pageReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void submitTransfer(Long id) { + // 校验存在 + 草稿状态 + MesWmTransferDO transfer = validateTransferExistsAndDraft(id); + List lines = transferLineService.getTransferLineListByTransferId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_TRANSFER_NO_LINE); + } + + // 配送模式下,提交后如果未确认,则进入待确认状态;否则直接进入待上架状态 + if (Boolean.TRUE.equals(transfer.getDeliveryFlag()) && !Boolean.TRUE.equals(transfer.getConfirmFlag())) { + transfer.setStatus(MesWmTransferStatusEnum.UNCONFIRMED.getStatus()).setConfirmFlag(false); + // DONE @AI:冻结库存属于主单状态流转的一部分,保留在主单 service 统一处理 + freezeTransferLineStocks(id, true); + } else { + transfer.setStatus(MesWmTransferStatusEnum.APPROVING.getStatus()); + } + transferMapper.updateById(transfer); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void confirmTransfer(Long id) { + // 校验存在 + 待确认状态 + MesWmTransferDO transfer = validateTransferExistsAndConfirm(id); + + // 更新状态:待确认 -> 待上架 + transfer.setStatus(MesWmTransferStatusEnum.APPROVING.getStatus()); + transfer.setConfirmFlag(true); + transferMapper.updateById(transfer); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void stockTransfer(Long id) { + // 1.1 校验存在 + MesWmTransferDO transfer = validateTransferExistsAndApproving(id); + List lines = transferLineService.getTransferLineListByTransferId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_TRANSFER_NO_LINE); + } + // 1.2 检查每个行的明细数量是否完成上架 + for (MesWmTransferLineDO line : lines) { + List details = transferDetailService.getTransferDetailListByLineId(line.getId()); + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details, + MesWmTransferDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); + if (line.getQuantity() != null && totalDetailQty.compareTo(line.getQuantity()) != 0) { + throw exception(WM_TRANSFER_DETAIL_QUANTITY_MISMATCH); + } + } + + // 2. 更新状态:待上架 -> 待执行 + transfer.setStatus(MesWmTransferStatusEnum.APPROVED.getStatus()); + transferMapper.updateById(transfer); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void finishTransfer(Long id) { + // 1. 校验存在 + 待执行状态 + MesWmTransferDO transfer = validateTransferExistsAndApproved(id); + List lines = transferLineService.getTransferLineListByTransferId(id); + if (CollUtil.isEmpty(lines)) { + throw exception(WM_TRANSFER_NO_LINE); + } + + // 2. 创建库存事务(调拨移出 + 调拨移入) + createTransferTransactions(transfer, lines); + + // 3. 更新状态:待执行 -> 已完成 + transfer.setStatus(MesWmTransferStatusEnum.FINISHED.getStatus()); + transferMapper.updateById(transfer); + + // 4. 配送模式下,执行完成后解除来源库存冻结 + if (Boolean.TRUE.equals(transfer.getDeliveryFlag())) { + freezeTransferLineStocks(id, false); + } + } + + /** + * 创建调拨事务:基于 detail (明细) 的视角,不是纯粹的 line(行)的视角。 + * 因为明细才代表了实际调往各个目标仓位的动作,所以每条明細产生一笔出库(MOVE_OUT)和一笔入库(MOVE_IN)。 + */ + private void createTransferTransactions(MesWmTransferDO transfer, List lines) { + // 1. 预加载所有明细,按 lineId 分组,避免 N+1 查询 + List allDetails = transferDetailService.getTransferDetailListByTransferId(transfer.getId()); + Map> detailMap = CollectionUtils.convertMultiMap( + allDetails, MesWmTransferDetailDO::getLineId); + // 2. 遍历行和对应的明细,创建事务 + for (MesWmTransferLineDO line : lines) { + List details = detailMap.getOrDefault(line.getId(), List.of()); + for (MesWmTransferDetailDO detail : details) { + // 2.1 先执行出库:调拨移出(从源仓库扣减库存),出库数量基于当前明细的数量 + Long outTransactionId = wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.MOVE_OUT.getType()).setItemId(line.getItemId()) + .setQuantity(detail.getQuantity().negate()) // 库存减少(按 detail 的数量出) + .setBatchId(line.getBatchId()) + .setWarehouseId(line.getFromWarehouseId()).setLocationId(line.getFromLocationId()).setAreaId(line.getFromAreaId()) + .setBizType(MesBizTypeConstants.WM_TRANSFER_OUT).setBizId(transfer.getId()) + .setBizCode(transfer.getCode()).setBizLineId(line.getId())); + // 2.2 再执行入库:调拨移入(向目标仓库增加库存),入库数量等于相同明细的数量 + wmTransactionService.createTransaction(new MesWmTransactionSaveReqDTO() + .setType(MesWmTransactionTypeEnum.MOVE_IN.getType()).setItemId(line.getItemId()) // 物料信息来自 line + .setQuantity(detail.getQuantity()) // 库存增加(按 detail 的数量入) + .setBatchId(line.getBatchId()) // 批次信息来自 line + .setWarehouseId(detail.getToWarehouseId()).setLocationId(detail.getToLocationId()).setAreaId(detail.getToAreaId()) + .setBizType(MesBizTypeConstants.WM_TRANSFER_IN).setBizId(transfer.getId()) + .setBizCode(transfer.getCode()).setBizLineId(line.getId()) + .setRelatedTransactionId(outTransactionId)); // 关联本次的具体出库事务 + } + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelTransfer(Long id) { + // 校验存在 + 非已完成/已取消状态 + MesWmTransferDO transfer = validateTransferExistsAndNotFinished(id); + + // 配送模式下,取消时需解除冻结 + if (Boolean.TRUE.equals(transfer.getDeliveryFlag())) { + freezeTransferLineStocks(id, false); + } + + // 更新状态 -> 已取消 + transfer.setStatus(MesWmTransferStatusEnum.CANCELED.getStatus()); + transferMapper.updateById(transfer); + } + + @Override + public MesWmTransferDO validateTransferEditable(Long id) { + MesWmTransferDO transfer = transferMapper.selectById(id); + if (transfer == null) { + throw exception(WM_TRANSFER_NOT_EXISTS); + } + if (!MesWmTransferStatusEnum.PREPARE.getStatus().equals(transfer.getStatus())) { + throw exception(WM_TRANSFER_NOT_EDITABLE); + } + return transfer; + } + + // ==================== 私有方法 ==================== + + private void validateCodeUnique(Long id, String code) { + MesWmTransferDO transfer = transferMapper.selectByCode(code); + if (transfer == null) { + return; + } + // 如果 id 为空,说明是新增,存在同名则报错 + if (id == null) { + throw exception(WM_TRANSFER_CODE_DUPLICATE); + } + // 如果 id 不为空,说明是修改,存在同名且不是自己则报错 + if (!transfer.getId().equals(id)) { + throw exception(WM_TRANSFER_CODE_DUPLICATE); + } + } + + private MesWmTransferDO validateTransferExistsAndDraft(Long id) { + MesWmTransferDO transfer = transferMapper.selectById(id); + if (transfer == null) { + throw exception(WM_TRANSFER_NOT_EXISTS); + } + if (!MesWmTransferStatusEnum.PREPARE.getStatus().equals(transfer.getStatus())) { + throw exception(WM_TRANSFER_NOT_DRAFT); + } + return transfer; + } + + private MesWmTransferDO validateTransferExistsAndConfirm(Long id) { + MesWmTransferDO transfer = transferMapper.selectById(id); + if (transfer == null) { + throw exception(WM_TRANSFER_NOT_EXISTS); + } + if (!MesWmTransferStatusEnum.UNCONFIRMED.getStatus().equals(transfer.getStatus())) { + throw exception(WM_TRANSFER_NOT_CONFIRMED); + } + return transfer; + } + + private MesWmTransferDO validateTransferExistsAndApproving(Long id) { + MesWmTransferDO transfer = transferMapper.selectById(id); + if (transfer == null) { + throw exception(WM_TRANSFER_NOT_EXISTS); + } + if (!MesWmTransferStatusEnum.APPROVING.getStatus().equals(transfer.getStatus())) { + throw exception(WM_TRANSFER_NOT_APPROVING); + } + return transfer; + } + + private MesWmTransferDO validateTransferExistsAndApproved(Long id) { + MesWmTransferDO transfer = transferMapper.selectById(id); + if (transfer == null) { + throw exception(WM_TRANSFER_NOT_EXISTS); + } + if (!MesWmTransferStatusEnum.APPROVED.getStatus().equals(transfer.getStatus())) { + throw exception(WM_TRANSFER_NOT_APPROVED); + } + return transfer; + } + + private MesWmTransferDO validateTransferExistsAndNotFinished(Long id) { + MesWmTransferDO transfer = transferMapper.selectById(id); + if (transfer == null) { + throw exception(WM_TRANSFER_NOT_EXISTS); + } + if (MesWmTransferStatusEnum.FINISHED.getStatus().equals(transfer.getStatus()) + || MesWmTransferStatusEnum.CANCELED.getStatus().equals(transfer.getStatus())) { + throw exception(WM_TRANSFER_ALREADY_FINISHED); + } + return transfer; + } + + private void freezeTransferLineStocks(Long transferId, boolean frozen) { + List lines = transferLineService.getTransferLineListByTransferId(transferId); + if (CollUtil.isEmpty(lines)) { + return; + } + List materialStockIds = convertList(lines, + MesWmTransferLineDO::getMaterialStockId, line -> line.getMaterialStockId() != null); + materialStockService.updateMaterialStockFrozen(materialStockIds, frozen); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseAreaService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseAreaService.java new file mode 100644 index 000000000..14fd03ca6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseAreaService.java @@ -0,0 +1,120 @@ +package cn.iocoder.yudao.module.mes.service.wm.warehouse; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area.MesWmWarehouseAreaPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area.MesWmWarehouseAreaSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 库位 Service 接口 + */ +public interface MesWmWarehouseAreaService { + + /** + * 创建库位 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWarehouseArea(@Valid MesWmWarehouseAreaSaveReqVO createReqVO); + + /** + * 更新库位 + * + * @param updateReqVO 更新信息 + */ + void updateWarehouseArea(@Valid MesWmWarehouseAreaSaveReqVO updateReqVO); + + /** + * 删除库位 + * + * @param id 编号 + */ + void deleteWarehouseArea(Long id); + + /** + * 校验库位存在 + * + * @param id 编号 + * @return 库位 + */ + MesWmWarehouseAreaDO validateWarehouseAreaExists(Long id); + + /** + * 获得库位 + * + * @param id 编号 + * @return 库位 + */ + MesWmWarehouseAreaDO getWarehouseArea(Long id); + + /** + * 获得库位分页 + * + * @param pageReqVO 分页参数 + * @return 库位分页 + */ + PageResult getWarehouseAreaPage(MesWmWarehouseAreaPageReqVO pageReqVO); + + /** + * 按库区获得库位列表 + * + * @param locationId 库区编号 + * @return 库位列表 + */ + List getWarehouseAreaList(Long locationId); + + /** + * 按编号集合获得库位列表 + * + * @param ids 编号集合 + * @return 库位列表 + */ + List getWarehouseAreaList(Collection ids); + + default Map getWarehouseAreaMap(Collection ids) { + return convertMap(getWarehouseAreaList(ids), MesWmWarehouseAreaDO::getId); + } + + /** + * 获得指定库区下的库位数量 + * + * @param locationId 库区编号 + * @return 库位数量 + */ + Long getWarehouseAreaCountByLocationId(Long locationId); + + /** + * 校验仓库、库区、库位的父子关系 + * + * @param warehouseId 仓库编号 + * @param locationId 库区编号 + * @param areaId 库位编号 + */ + void validateWarehouseAreaExists(Long warehouseId, Long locationId, Long areaId); + + /** + * 批量设置指定库区下所有库位的混放规则 + * + * @param locationId 库区编号 + * @param allowItemMixing 是否允许物料混放(null 表示不修改) + * @param allowBatchMixing 是否允许批次混放(null 表示不修改) + */ + void updateByLocationId(Long locationId, Boolean allowItemMixing, Boolean allowBatchMixing); + + /** + * 按编码获得库位(如果是虚拟线边库位编码且不存在,会自动插入) + * + * @param code 编码 + * @return 库位 + */ + MesWmWarehouseAreaDO getWarehouseAreaByCode(String code); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseAreaServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseAreaServiceImpl.java new file mode 100644 index 000000000..33a7a476e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseAreaServiceImpl.java @@ -0,0 +1,241 @@ +package cn.iocoder.yudao.module.mes.service.wm.warehouse; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area.MesWmWarehouseAreaPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area.MesWmWarehouseAreaSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse.MesWmWarehouseAreaMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 库位 Service 实现类 + */ +@Service +@Validated +public class MesWmWarehouseAreaServiceImpl implements MesWmWarehouseAreaService { + + @Resource + private MesWmWarehouseAreaMapper areaMapper; + + @Resource + @Lazy + private MesMdWorkstationService workstationService; + @Resource + @Lazy + private MesWmMaterialStockService materialStockService; + @Resource + @Lazy + private MesWmWarehouseLocationService locationService; + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createWarehouseArea(MesWmWarehouseAreaSaveReqVO createReqVO) { + // 校验虚拟库位不允许新增 + validateNotVirtual(createReqVO.getCode()); + // 校验数据 + validateWarehouseAreaSaveData(createReqVO); + + // 插入 + MesWmWarehouseAreaDO area = BeanUtils.toBean(createReqVO, MesWmWarehouseAreaDO.class); + areaMapper.insert(area); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.AREA.getValue(), + area.getId(), area.getCode(), area.getName()); + return area.getId(); + } + + @Override + public void updateWarehouseArea(MesWmWarehouseAreaSaveReqVO updateReqVO) { + // 校验存在 + MesWmWarehouseAreaDO area = validateWarehouseAreaExists(updateReqVO.getId()); + // 校验虚拟库位不允许修改 + validateNotVirtual(area.getCode()); + // 校验数据 + validateWarehouseAreaSaveData(updateReqVO); + + // 更新 + MesWmWarehouseAreaDO updateObj = BeanUtils.toBean(updateReqVO, MesWmWarehouseAreaDO.class); + areaMapper.updateById(updateObj); + } + + private void validateWarehouseAreaSaveData(MesWmWarehouseAreaSaveReqVO reqVO) { + // 校验库区存在 + locationService.validateWarehouseLocationExists(reqVO.getLocationId()); + // 校验编码唯一 + validateWarehouseAreaCodeUnique(reqVO.getId(), reqVO.getLocationId(), reqVO.getCode()); + // 校验名称唯一 + validateWarehouseAreaNameUnique(reqVO.getId(), reqVO.getLocationId(), reqVO.getName()); + } + + private void validateNotVirtual(String code) { + if (MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA.equals(code)) { + throw exception(WM_WAREHOUSE_AREA_IS_VIRTUAL); + } + } + + @Override + public void deleteWarehouseArea(Long id) { + // 校验存在 + MesWmWarehouseAreaDO area = validateWarehouseAreaExists(id); + // 校验虚拟库位不允许删除 + validateNotVirtual(area.getCode()); + // 校验是否被工作站引用 + if (workstationService.getWorkstationCountByAreaId(id) > 0) { + throw exception(WM_WAREHOUSE_AREA_HAS_WORKSTATION); + } + // 校验是否有库存记录 + if (materialStockService.getMaterialStockCountByAreaId(id) > 0) { + throw exception(WM_WAREHOUSE_AREA_HAS_MATERIAL_STOCK); + } + + // 删除 + areaMapper.deleteById(id); + } + + @Override + public MesWmWarehouseAreaDO validateWarehouseAreaExists(Long id) { + MesWmWarehouseAreaDO area = areaMapper.selectById(id); + if (area == null) { + throw exception(WM_WAREHOUSE_AREA_NOT_EXISTS); + } + return area; + } + + private void validateWarehouseAreaCodeUnique(Long id, Long locationId, String code) { + MesWmWarehouseAreaDO area = areaMapper.selectByCode(locationId, code); + if (area == null) { + return; + } + if (ObjUtil.notEqual(area.getId(), id)) { + throw exception(WM_WAREHOUSE_AREA_CODE_DUPLICATE); + } + } + + private void validateWarehouseAreaNameUnique(Long id, Long locationId, String name) { + MesWmWarehouseAreaDO area = areaMapper.selectByName(locationId, name); + if (area == null) { + return; + } + if (ObjUtil.notEqual(area.getId(), id)) { + throw exception(WM_WAREHOUSE_AREA_NAME_DUPLICATE); + } + } + + @Override + public MesWmWarehouseAreaDO getWarehouseArea(Long id) { + return areaMapper.selectById(id); + } + + @Override + public PageResult getWarehouseAreaPage(MesWmWarehouseAreaPageReqVO pageReqVO) { + return areaMapper.selectPage(pageReqVO); + } + + @Override + public List getWarehouseAreaList(Long locationId) { + return areaMapper.selectSimpleList(locationId); + } + + @Override + public List getWarehouseAreaList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return areaMapper.selectListByIds(ids); + } + + @Override + public Long getWarehouseAreaCountByLocationId(Long locationId) { + return areaMapper.selectCountByLocationId(locationId); + } + + @Override + public void validateWarehouseAreaExists(Long warehouseId, Long locationId, Long areaId) { + if (areaId == null) { + return; + } + // 1.1 校验库位存在 + MesWmWarehouseAreaDO area = validateWarehouseAreaExists(areaId); + // 1.2 校验库位所属的库区是否匹配 + if (locationId != null && ObjUtil.notEqual(area.getLocationId(), locationId)) { + throw exception(WM_WAREHOUSE_AREA_RELATION_INVALID); + } + // 2. 校验库区存在 + if (locationId != null) { + locationService.validateWarehouseLocationExists(locationId); + } + // 3. 校验仓库存在(通过库区的 locationId 关联查询) + if (warehouseId != null) { + MesWmWarehouseLocationDO location = locationService.validateWarehouseLocationExists(area.getLocationId()); + if (location != null && ObjUtil.notEqual(location.getWarehouseId(), warehouseId)) { + throw exception(WM_WAREHOUSE_AREA_WAREHOUSE_MISMATCH); + } + } + } + + @Override + public void updateByLocationId(Long locationId, Boolean allowItemMixing, Boolean allowBatchMixing) { + // 校验库区存在 + locationService.validateWarehouseLocationExists(locationId); + // 构建更新对象 + MesWmWarehouseAreaDO updateObj = new MesWmWarehouseAreaDO(); + if (allowItemMixing != null) { + updateObj.setAllowItemMixing(allowItemMixing); + } + if (allowBatchMixing != null) { + updateObj.setAllowBatchMixing(allowBatchMixing); + } + // 批量更新库位 + areaMapper.updateByLocationId(locationId, updateObj); + } + + @Override + public MesWmWarehouseAreaDO getWarehouseAreaByCode(String code) { + // 1. 查询库位,存在则直接返回 + MesWmWarehouseAreaDO area = areaMapper.selectByCode(code); + if (area != null) { + return area; + } + + // 2. 如果是虚拟线边库位编码,则自动初始化 + if (MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA.equals(code)) { + // 2.1 先确保虚拟库区存在(getWarehouseLocationByCode 会级联创建仓库 + 库区) + MesWmWarehouseLocationDO location = locationService.getWarehouseLocationByCode( + MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + Assert.notNull(location, "虚拟库区必须存在"); + // 2.2 自动初始化 + MesWmWarehouseAreaDO newArea = MesWmWarehouseAreaDO.builder() + .locationId(location.getId()).code(code).name("虚拟线边库位") + .status(CommonStatusEnum.ENABLE.getStatus()).frozen(false) + .allowItemMixing(true).allowBatchMixing(true) + .remark("系统自动初始化的虚拟线边库位") + .build(); + areaMapper.insert(newArea); + return newArea; + } + return null; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationService.java new file mode 100644 index 000000000..f9faab372 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationService.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.service.wm.warehouse; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 库区 Service 接口 + */ +public interface MesWmWarehouseLocationService { + + /** + * 创建库区 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWarehouseLocation(@Valid MesWmWarehouseLocationSaveReqVO createReqVO); + + /** + * 更新库区 + * + * @param updateReqVO 更新信息 + */ + void updateWarehouseLocation(@Valid MesWmWarehouseLocationSaveReqVO updateReqVO); + + /** + * 删除库区 + * + * @param id 编号 + */ + void deleteWarehouseLocation(Long id); + + /** + * 校验库区存在 + * + * @param id 编号 + * @return 库区 + */ + MesWmWarehouseLocationDO validateWarehouseLocationExists(Long id); + + /** + * 获得库区 + * + * @param id 编号 + * @return 库区 + */ + MesWmWarehouseLocationDO getWarehouseLocation(Long id); + + /** + * 获得库区分页 + * + * @param pageReqVO 分页参数 + * @return 库区分页 + */ + PageResult getWarehouseLocationPage(MesWmWarehouseLocationPageReqVO pageReqVO); + + /** + * 按仓库获得库区列表 + * + * @param warehouseId 仓库编号 + * @return 库区列表 + */ + List getWarehouseLocationList(Long warehouseId); + + /** + * 按编号集合获得库区列表 + * + * @param ids 编号集合 + * @return 库区列表 + */ + List getWarehouseLocationList(Collection ids); + + default Map getWarehouseLocationMap(Collection ids) { + return convertMap(getWarehouseLocationList(ids), MesWmWarehouseLocationDO::getId); + } + + /** + * 获得指定仓库下的库区数量 + * + * @param warehouseId 仓库编号 + * @return 库区数量 + */ + Long getWarehouseLocationCountByWarehouseId(Long warehouseId); + + /** + * 按编码获得库区(如果是虚拟线边库区编码且不存在,会自动插入) + * + * @param code 编码 + * @return 库区 + */ + MesWmWarehouseLocationDO getWarehouseLocationByCode(String code); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationServiceImpl.java new file mode 100644 index 000000000..d2177b06d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationServiceImpl.java @@ -0,0 +1,202 @@ +package cn.iocoder.yudao.module.mes.service.wm.warehouse; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse.MesWmWarehouseLocationMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 库区 Service 实现类 + */ +@Service +@Validated +public class MesWmWarehouseLocationServiceImpl implements MesWmWarehouseLocationService { + + @Resource + private MesWmWarehouseLocationMapper locationMapper; + + @Resource + private MesWmWarehouseAreaService areaService; + @Resource + @Lazy + private MesMdWorkstationService workstationService; + @Resource + private MesWmMaterialStockService materialStockService; + @Resource + @Lazy + private MesWmWarehouseService warehouseService; + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createWarehouseLocation(MesWmWarehouseLocationSaveReqVO createReqVO) { + // 校验虚拟库区不允许新增 + validateNotVirtual(createReqVO.getCode()); + // 校验数据 + validateWarehouseLocationSaveData(createReqVO); + + // 插入 + MesWmWarehouseLocationDO location = BeanUtils.toBean(createReqVO, MesWmWarehouseLocationDO.class); + locationMapper.insert(location); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.LOCATION.getValue(), + location.getId(), location.getCode(), location.getName()); + return location.getId(); + } + + @Override + public void updateWarehouseLocation(MesWmWarehouseLocationSaveReqVO updateReqVO) { + // 校验存在 + MesWmWarehouseLocationDO location = validateWarehouseLocationExists(updateReqVO.getId()); + // 校验虚拟库区不允许修改 + validateNotVirtual(location.getCode()); + // 校验数据 + validateWarehouseLocationSaveData(updateReqVO); + + // 更新 + MesWmWarehouseLocationDO updateObj = BeanUtils.toBean(updateReqVO, MesWmWarehouseLocationDO.class); + locationMapper.updateById(updateObj); + } + + private void validateWarehouseLocationSaveData(MesWmWarehouseLocationSaveReqVO reqVO) { + // 校验仓库存在 + warehouseService.validateWarehouseExists(reqVO.getWarehouseId()); + // 校验编码唯一 + validateWarehouseLocationCodeUnique(reqVO.getId(), reqVO.getWarehouseId(), reqVO.getCode()); + // 校验名称唯一 + validateWarehouseLocationNameUnique(reqVO.getId(), reqVO.getWarehouseId(), reqVO.getName()); + } + + private void validateNotVirtual(String code) { + if (MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION.equals(code)) { + throw exception(WM_WAREHOUSE_LOCATION_IS_VIRTUAL); + } + } + + @Override + public void deleteWarehouseLocation(Long id) { + // 校验存在 + MesWmWarehouseLocationDO location = validateWarehouseLocationExists(id); + // 校验虚拟库区不允许删除 + validateNotVirtual(location.getCode()); + // 校验是否有库位 + if (areaService.getWarehouseAreaCountByLocationId(id) > 0) { + throw exception(WM_WAREHOUSE_LOCATION_HAS_AREA); + } + // 校验是否被工作站引用 + if (workstationService.getWorkstationCountByLocationId(id) > 0) { + throw exception(WM_WAREHOUSE_LOCATION_HAS_WORKSTATION); + } + // 校验是否有库存记录 + if (materialStockService.getMaterialStockCountByLocationId(id) > 0) { + throw exception(WM_WAREHOUSE_LOCATION_HAS_MATERIAL_STOCK); + } + + // 删除 + locationMapper.deleteById(id); + } + + @Override + public MesWmWarehouseLocationDO validateWarehouseLocationExists(Long id) { + MesWmWarehouseLocationDO location = locationMapper.selectById(id); + if (location == null) { + throw exception(WM_WAREHOUSE_LOCATION_NOT_EXISTS); + } + return location; + } + + private void validateWarehouseLocationCodeUnique(Long id, Long warehouseId, String code) { + MesWmWarehouseLocationDO location = locationMapper.selectByCode(warehouseId, code); + if (location == null) { + return; + } + if (ObjUtil.notEqual(location.getId(), id)) { + throw exception(WM_WAREHOUSE_LOCATION_CODE_DUPLICATE); + } + } + + private void validateWarehouseLocationNameUnique(Long id, Long warehouseId, String name) { + MesWmWarehouseLocationDO location = locationMapper.selectByName(warehouseId, name); + if (location == null) { + return; + } + if (ObjUtil.notEqual(location.getId(), id)) { + throw exception(WM_WAREHOUSE_LOCATION_NAME_DUPLICATE); + } + } + + @Override + public MesWmWarehouseLocationDO getWarehouseLocation(Long id) { + return locationMapper.selectById(id); + } + + @Override + public PageResult getWarehouseLocationPage(MesWmWarehouseLocationPageReqVO pageReqVO) { + return locationMapper.selectPage(pageReqVO); + } + + @Override + public List getWarehouseLocationList(Long warehouseId) { + return locationMapper.selectSimpleList(warehouseId); + } + + @Override + public List getWarehouseLocationList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return locationMapper.selectListByIds(ids); + } + + @Override + public Long getWarehouseLocationCountByWarehouseId(Long warehouseId) { + return locationMapper.selectCountByWarehouseId(warehouseId); + } + + @Override + public MesWmWarehouseLocationDO getWarehouseLocationByCode(String code) { + // 1. 查询库区,存在则直接返回 + MesWmWarehouseLocationDO location = locationMapper.selectByCode(code); + if (location != null) { + return location; + } + + // 2. 如果是虚拟线边库区编码,则自动初始化 + if (MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION.equals(code)) { + // 2.1 先确保虚拟仓库存在(getWarehouseByCode 会级联创建仓库) + MesWmWarehouseDO warehouse = warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + cn.hutool.core.lang.Assert.notNull(warehouse, "虚拟仓库必须存在"); + // 2.2 自动初始化 + MesWmWarehouseLocationDO newLocation = MesWmWarehouseLocationDO.builder() + .warehouseId(warehouse.getId()).code(code).name("虚拟线边库区") + .areaStatus(cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus()) + .frozen(false).remark("系统自动初始化的虚拟线边库区") + .build(); + locationMapper.insert(newLocation); + return newLocation; + } + return null; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseService.java new file mode 100644 index 000000000..c038d5a7e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseService.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.mes.service.wm.warehouse; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehousePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehouseSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 仓库 Service 接口 + */ +public interface MesWmWarehouseService { + + /** + * 创建仓库 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWarehouse(@Valid MesWmWarehouseSaveReqVO createReqVO); + + /** + * 更新仓库 + * + * @param updateReqVO 更新信息 + */ + void updateWarehouse(@Valid MesWmWarehouseSaveReqVO updateReqVO); + + /** + * 删除仓库 + * + * @param id 编号 + */ + void deleteWarehouse(Long id); + + /** + * 校验仓库存在 + * + * @param id 编号 + * @return 仓库 + */ + MesWmWarehouseDO validateWarehouseExists(Long id); + + /** + * 获得仓库 + * + * @param id 编号 + * @return 仓库 + */ + MesWmWarehouseDO getWarehouse(Long id); + + /** + * 获得仓库分页 + * + * @param pageReqVO 分页参数 + * @return 仓库分页 + */ + PageResult getWarehousePage(MesWmWarehousePageReqVO pageReqVO); + + /** + * 获得仓库列表 + * + * @return 仓库列表 + */ + List getWarehouseList(); + + /** + * 按编号集合获得仓库列表 + * + * @param ids 编号集合 + * @return 仓库列表 + */ + List getWarehouseList(Collection ids); + + default Map getWarehouseMap(Collection ids) { + return convertMap(getWarehouseList(ids), MesWmWarehouseDO::getId); + } + + /** + * 按编码获得仓库(如果是虚拟线边库编码且不存在,会自动插入) + * + * @param code 编码 + * @return 仓库 + */ + MesWmWarehouseDO getWarehouseByCode(String code); + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseServiceImpl.java new file mode 100644 index 000000000..bd85c1466 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseServiceImpl.java @@ -0,0 +1,186 @@ +package cn.iocoder.yudao.module.mes.service.wm.warehouse; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehousePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.MesWmWarehouseSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse.MesWmWarehouseMapper; +import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 仓库 Service 实现类 + */ +@Service +@Validated +public class MesWmWarehouseServiceImpl implements MesWmWarehouseService { + + @Resource + private MesWmWarehouseMapper warehouseMapper; + + @Resource + private MesWmWarehouseLocationService locationService; + @Resource + @Lazy + private MesMdWorkstationService workstationService; + @Resource + private MesWmMaterialStockService materialStockService; + @Resource + private MesWmBarcodeService barcodeService; + + @Override + public Long createWarehouse(MesWmWarehouseSaveReqVO createReqVO) { + // 校验虚拟仓库不允许新增 + validateNotVirtual(createReqVO.getCode()); + // 校验数据 + validateWarehouseSaveData(createReqVO); + + // 插入 + MesWmWarehouseDO warehouse = BeanUtils.toBean(createReqVO, MesWmWarehouseDO.class); + warehouseMapper.insert(warehouse); + + // 自动生成条码 + barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.WAREHOUSE.getValue(), + warehouse.getId(), warehouse.getCode(), warehouse.getName()); + return warehouse.getId(); + } + + @Override + public void updateWarehouse(MesWmWarehouseSaveReqVO updateReqVO) { + // 校验存在 + MesWmWarehouseDO warehouse = validateWarehouseExists(updateReqVO.getId()); + // 校验虚拟仓库不允许修改 + validateNotVirtual(warehouse.getCode()); + // 校验数据 + validateWarehouseSaveData(updateReqVO); + + // 更新 + MesWmWarehouseDO updateObj = BeanUtils.toBean(updateReqVO, MesWmWarehouseDO.class); + warehouseMapper.updateById(updateObj); + } + + private void validateWarehouseSaveData(MesWmWarehouseSaveReqVO reqVO) { + // 校验编码唯一 + validateWarehouseCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验名称唯一 + validateWarehouseNameUnique(reqVO.getId(), reqVO.getName()); + } + + private void validateNotVirtual(String code) { + if (MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE.equals(code)) { + throw exception(WM_WAREHOUSE_IS_VIRTUAL); + } + } + + @Override + public void deleteWarehouse(Long id) { + // 校验存在 + MesWmWarehouseDO warehouse = validateWarehouseExists(id); + // 校验虚拟仓库不允许删除 + validateNotVirtual(warehouse.getCode()); + // 校验是否有库区 + if (locationService.getWarehouseLocationCountByWarehouseId(id) > 0) { + throw exception(WM_WAREHOUSE_HAS_LOCATION); + } + // 校验是否被工作站引用 + if (workstationService.getWorkstationCountByWarehouseId(id) > 0) { + throw exception(WM_WAREHOUSE_HAS_WORKSTATION); + } + // 校验是否有库存记录 + if (materialStockService.getMaterialStockCountByWarehouseId(id) > 0) { + throw exception(WM_WAREHOUSE_HAS_MATERIAL_STOCK); + } + + // 删除 + warehouseMapper.deleteById(id); + } + + @Override + public MesWmWarehouseDO validateWarehouseExists(Long id) { + MesWmWarehouseDO warehouse = warehouseMapper.selectById(id); + if (warehouse == null) { + throw exception(WM_WAREHOUSE_NOT_EXISTS); + } + return warehouse; + } + + private void validateWarehouseCodeUnique(Long id, String code) { + MesWmWarehouseDO warehouse = warehouseMapper.selectByCode(code); + if (warehouse == null) { + return; + } + if (ObjUtil.notEqual(warehouse.getId(), id)) { + throw exception(WM_WAREHOUSE_CODE_DUPLICATE); + } + } + + private void validateWarehouseNameUnique(Long id, String name) { + MesWmWarehouseDO warehouse = warehouseMapper.selectByName(name); + if (warehouse == null) { + return; + } + if (ObjUtil.notEqual(warehouse.getId(), id)) { + throw exception(WM_WAREHOUSE_NAME_DUPLICATE); + } + } + + @Override + public MesWmWarehouseDO getWarehouse(Long id) { + return warehouseMapper.selectById(id); + } + + @Override + public PageResult getWarehousePage(MesWmWarehousePageReqVO pageReqVO) { + return warehouseMapper.selectPage(pageReqVO); + } + + @Override + public List getWarehouseList() { + return warehouseMapper.selectSimpleList(); + } + + @Override + public List getWarehouseList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return warehouseMapper.selectListByIds(ids); + } + + @Override + public MesWmWarehouseDO getWarehouseByCode(String code) { + // 1. 查询仓库,存在则直接返回 + MesWmWarehouseDO warehouse = warehouseMapper.selectByCode(code); + if (warehouse != null) { + return warehouse; + } + + // 2. 如果是虚拟线边库编码,则自动初始化 + if (MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE.equals(code)) { + MesWmWarehouseDO newWarehouse = MesWmWarehouseDO.builder() + .code(code).name("虚拟线边仓库").frozen(false) + .remark("系统自动初始化的虚拟线边仓库(用于生产报工与在制品管理解耦)") + .build(); + warehouseMapper.insert(newWarehouse); + return newWarehouse; + } + return null; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/resources/application-dev.yaml b/yudao-module-mes/yudao-module-mes-server/src/main/resources/application-dev.yaml new file mode 100644 index 000000000..5aa446f5d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/resources/application-dev.yaml @@ -0,0 +1,120 @@ +--- #################### 注册中心 + 配置中心相关配置 #################### + +spring: + cloud: + nacos: + server-addr: 127.0.0.1:8848 # Nacos 服务器地址 + username: # Nacos 账号 + password: # Nacos 密码 + discovery: # 【配置中心】配置项 + namespace: dev # 命名空间。这里使用 dev 开发环境 + group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + metadata: + version: 1.0.0 # 服务实例的版本号,可用于灰度发布 + config: # 【注册中心】配置项 + namespace: dev # 命名空间。这里使用 dev 开发环境 + group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + +--- #################### 数据库相关配置 #################### +spring: + # 数据源配置项 + autoconfigure: + exclude: + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 5 # 初始连接数 + min-idle: 10 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒(1 分钟) + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒(10 分钟) + max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒(30 分钟) + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + pool-prepared-statements: true # 是否开启 PreparedStatement 缓存 + max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量 + primary: master + datasource: + master: + url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 + username: root + password: 123456 + slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改 + lazy: true # 开启懒加载,保证启动速度 + url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 + username: root + password: 123456 + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + data: + redis: + host: 400-infra.server.iocoder.cn # 地址 + port: 6379 # 端口 + database: 1 # 数据库索引 +# password: 123456 # 密码,建议生产环境开启 + +--- #################### MQ 消息队列相关配置 #################### + +--- #################### 定时任务相关配置 #################### +xxl: + job: + enabled: false # 是否开启调度中心,默认为 true 开启 + admin: + addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址 + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项 +lock4j: + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 + +--- #################### 监控相关配置 #################### + +# Actuator 监控端点的配置项 +management: + endpoints: + web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator + exposure: + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 + +# Spring Boot Admin 配置项 +spring: + boot: + admin: + # Spring Boot Admin Client 客户端的相关配置 + client: + instance: + service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] + username: admin + password: admin + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + access-log: # 访问日志的配置项 + enable: false + demo: false # 关闭演示模式 diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/resources/application-local.yaml b/yudao-module-mes/yudao-module-mes-server/src/main/resources/application-local.yaml new file mode 100644 index 000000000..dc530ef9c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/resources/application-local.yaml @@ -0,0 +1,139 @@ +--- #################### 注册中心 + 配置中心相关配置 #################### + +spring: + cloud: + nacos: + server-addr: 127.0.0.1:8848 # Nacos 服务器地址 + username: # Nacos 账号 + password: # Nacos 密码 + discovery: # 【配置中心】配置项 + namespace: dev # 命名空间。这里使用 dev 开发环境 + group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + metadata: + version: 1.0.0 # 服务实例的版本号,可用于灰度发布 + config: # 【注册中心】配置项 + namespace: dev # 命名空间。这里使用 dev 开发环境 + group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + +--- #################### 数据库相关配置 #################### +spring: + # 数据源配置项 + autoconfigure: + exclude: + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 1 # 初始连接数 + min-idle: 1 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒(1 分钟) + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒(10 分钟) + max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒(30 分钟) + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + pool-prepared-statements: true # 是否开启 PreparedStatement 缓存 + max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量 + primary: master + datasource: + master: + url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=ruoyi-vue-pro # SQLServer 连接的示例 + # url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 + username: root + password: 123456 + # username: sa # SQL Server 连接的示例 + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # SQL Server 连接的示例 + # username: SYSDBA # DM 连接的示例 + # password: SYSDBA # DM 连接的示例 + slave: # 模拟从库,可根据自己需要修改 + lazy: true # 开启懒加载,保证启动速度 + url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true + username: root + password: 123456 + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + data: + redis: + host: 127.0.0.1 # 地址 + port: 6379 # 端口 + database: 0 # 数据库索引 +# password: 123456 # 密码,建议生产环境开启 + +--- #################### MQ 消息队列相关配置 #################### + +--- #################### 定时任务相关配置 #################### +xxl: + job: + enabled: false # 是否开启调度中心,默认为 true 开启 + admin: + addresses: http://127.0.0.1:9090/xxl-job-admin # 调度中心部署跟地址 + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项 +lock4j: + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 + +--- #################### 监控相关配置 #################### + +# Actuator 监控端点的配置项 +management: + endpoints: + web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator + exposure: + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 + +# Spring Boot Admin 配置项 +spring: + boot: + admin: + # Spring Boot Admin Client 客户端的相关配置 + client: + instance: + service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] + username: admin + password: admin + +# 日志文件配置 +logging: + level: + # 配置自己写的 MyBatis Mapper 打印日志 + cn.iocoder.yudao.module.mes.dal.mysql: debug + org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + env: # 多环境的配置项 + tag: ${HOSTNAME} + security: + mock-enable: true + access-log: # 访问日志的配置项 + enable: false diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/resources/application.yaml b/yudao-module-mes/yudao-module-mes-server/src/main/resources/application.yaml new file mode 100644 index 000000000..4e4328edb --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/resources/application.yaml @@ -0,0 +1,124 @@ +spring: + application: + name: mes-server + + profiles: + active: local + + main: + allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 + allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务 + + config: + import: + - optional:classpath:application-${spring.profiles.active}.yaml # 加载【本地】配置 + - optional:nacos:${spring.application.name}-${spring.profiles.active}.yaml # 加载【Nacos】的配置 + + # Servlet 配置 + servlet: + # 文件上传相关配置项 + multipart: + max-file-size: 16MB # 单个文件大小 + max-request-size: 32MB # 设置总上传的文件大小 + + # Jackson 配置项 + jackson: + serialization: + write-dates-as-timestamps: true # 设置 LocalDateTime 的格式,使用时间戳 + write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401 + write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 + fail-on-empty-beans: false # 允许序列化无属性的 Bean + + # Cache 配置项 + cache: + type: REDIS + redis: + time-to-live: 1h # 设置过期时间为 1 小时 + +server: + port: 48091 + +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + +--- #################### 接口文档配置 #################### + +springdoc: + api-docs: + enabled: true # 1. 是否开启 Swagger 接文档的元数据 + path: /v3/api-docs + swagger-ui: + enabled: true # 2.1 是否开启 Swagger 文档的官方 UI 界面 + path: /swagger-ui + default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 + +knife4j: + enable: true + setting: + language: zh_cn + +# MyBatis Plus 的配置项 +mybatis-plus: + configuration: + map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 + global-config: + db-config: + id-type: NONE # "智能"模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。 + # id-type: AUTO # 自增 ID,适合 MySQL 等直接自增的数据库 + # id-type: INPUT # 用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库 + # id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解 + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) + banner: false # 关闭控制台的 Banner 打印 + type-aliases-package: ${yudao.info.base-package}.dal.dataobject + encryptor: + password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 + +mybatis-plus-join: + banner: false # 关闭控制台的 Banner 打印 + +# Spring Data Redis 配置 +spring: + data: + redis: + repositories: + enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度 + +# VO 转换(数据翻译)相关 +easy-trans: + is-enable-global: false # 【默认禁用,对性能确认压力大】启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + +--- #################### MQ 消息队列相关配置 #################### + +--- #################### 定时任务相关配置 #################### + +xxl: + job: + executor: + appname: ${spring.application.name} # 执行器 AppName + logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径 + accessToken: default_token # 执行器通讯TOKEN + +--- #################### 芋道相关配置 #################### + +yudao: + info: + version: 1.0.0 + base-package: cn.iocoder.yudao.module.mes + web: + admin-ui: + url: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址 + xss: + enable: false + exclude-urls: # 如下 url,仅仅是为了演示,去掉配置也没关系 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + swagger: + title: 管理后台 + description: 提供管理员管理的所有功能 + version: ${yudao.info.version} + tenant: # 多租户相关配置项 + enable: true + ignore-urls: + +debug: false diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/resources/logback-spring.xml b/yudao-module-mes/yudao-module-mes-server/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..15b28cfdf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/resources/logback-spring.xml @@ -0,0 +1,56 @@ + + + + + + + + +       + + ${CONSOLE_LOG_PATTERN} + + + + + + + + ${FILE_LOG_PATTERN} + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd}.%i.log + 30 + 10MB + + + + + 0 + 512 + + + + + + + + + + + + + + + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/home/MesHomeStatisticsMapper.xml b/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/home/MesHomeStatisticsMapper.xml new file mode 100644 index 000000000..33d6f0069 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/home/MesHomeStatisticsMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml b/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml new file mode 100644 index 000000000..ce2de7cbf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml @@ -0,0 +1,180 @@ + + + + + + + + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/wm/batch/MesWmBatchMapper.xml b/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/wm/batch/MesWmBatchMapper.xml new file mode 100644 index 000000000..4d71f7ff7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/main/resources/mapper/wm/batch/MesWmBatchMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImplTest.java new file mode 100644 index 000000000..a566df9d2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImplTest.java @@ -0,0 +1,175 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodeRecordMapper; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesMdAutoCodeRecordServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@ExtendWith(MockitoExtension.class) +public class MesMdAutoCodeRecordServiceImplTest { + + @InjectMocks + private MesMdAutoCodeRecordServiceImpl recordService; + + @Mock + private MesMdAutoCodeRecordMapper recordMapper; + + @Mock + private MesMdAutoCodeRuleService ruleService; + @Mock + private MesMdAutoCodePartService partService; + + @Mock + private MesMdAutoCodePartStrategy fixedCharStrategy; + @Mock + private MesMdAutoCodePartStrategy serialNumberStrategy; + @Mock + private MesMdAutoCodePartStrategy inputCharStrategy; + @Mock + private MesMdAutoCodePartStrategy dateStrategy; + + @BeforeEach + public void setUp() { + // 使用反射注入 strategyList + List strategyList = Arrays.asList( + fixedCharStrategy, serialNumberStrategy, inputCharStrategy, dateStrategy + ); + when(fixedCharStrategy.getType()).thenReturn(MesMdAutoCodePartTypeEnum.FIXED_CHAR.getType()); + when(serialNumberStrategy.getType()).thenReturn(MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType()); + when(inputCharStrategy.getType()).thenReturn(MesMdAutoCodePartTypeEnum.INPUT_CHAR.getType()); + when(dateStrategy.getType()).thenReturn(MesMdAutoCodePartTypeEnum.DATE.getType()); + ReflectUtil.setFieldValue(recordService, "strategyList", strategyList); + // 手动调用 init 方法初始化策略 map + recordService.init(); + } + + @Test + public void testGenerateAutoCode_fixedCharAndSerialNumber() { + // 准备参数 + String ruleCode = "ITEM_CODE"; + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(1L).setCode(ruleCode).setPadded(false); + MesMdAutoCodePartDO part1 = new MesMdAutoCodePartDO().setType(MesMdAutoCodePartTypeEnum.FIXED_CHAR.getType()) + .setFixCharacter("ITEM_").setLength(5).setSort(1); + MesMdAutoCodePartDO part2 = new MesMdAutoCodePartDO().setType(MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType()) + .setSerialStartNo(1).setSerialStep(1).setLength(4).setSort(2).setCycleFlag(false); + // mock + when(ruleService.getAutoCodeRuleByCode(ruleCode)).thenReturn(rule); + when(partService.getAutoCodePartListByRuleId(1L)).thenReturn(Arrays.asList(part1, part2)); + when(fixedCharStrategy.generate(eq(part1), any(MesMdAutoCodeContext.class))).thenReturn("ITEM_"); + when(serialNumberStrategy.generate(eq(part2), any(MesMdAutoCodeContext.class))).thenAnswer(invocation -> { + MesMdAutoCodeContext context = invocation.getArgument(1); + context.setSerialNo(1L); + return "0001"; + }); + when(recordMapper.selectByResult("ITEM_0001")).thenReturn(null); + + // 调用 + String result = recordService.generateAutoCode(ruleCode, null); + // 断言 + assertEquals("ITEM_0001", result); + ArgumentCaptor captor = ArgumentCaptor.forClass(MesMdAutoCodeRecordDO.class); + verify(recordMapper).insert(captor.capture()); + MesMdAutoCodeRecordDO record = captor.getValue(); + assertEquals(1L, record.getRuleId()); + assertEquals("ITEM_0001", record.getResult()); + assertEquals(1, record.getSerialNo()); + } + + @Test + public void testGenerateAutoCode_withInputChar() { + // 准备参数 + String ruleCode = "CLIENT_CODE"; + String inputChar = "A"; + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(2L).setCode(ruleCode).setPadded(false); + MesMdAutoCodePartDO part1 = new MesMdAutoCodePartDO().setType(MesMdAutoCodePartTypeEnum.INPUT_CHAR.getType()) + .setLength(1).setSort(1); + MesMdAutoCodePartDO part2 = new MesMdAutoCodePartDO().setType(MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType()) + .setSerialStartNo(1).setSerialStep(1).setLength(4).setSort(2).setCycleFlag(false); + // mock + when(ruleService.getAutoCodeRuleByCode(ruleCode)).thenReturn(rule); + when(partService.getAutoCodePartListByRuleId(2L)).thenReturn(Arrays.asList(part1, part2)); + when(inputCharStrategy.generate(eq(part1), any(MesMdAutoCodeContext.class))).thenReturn("A"); + when(serialNumberStrategy.generate(eq(part2), any(MesMdAutoCodeContext.class))).thenReturn("0001"); + when(recordMapper.selectByResult("A0001")).thenReturn(null); + + // 调用 + String result = recordService.generateAutoCode(ruleCode, inputChar); + // 断言 + assertEquals("A0001", result); + ArgumentCaptor captor = ArgumentCaptor.forClass(MesMdAutoCodeRecordDO.class); + verify(recordMapper).insert(captor.capture()); + MesMdAutoCodeRecordDO record = captor.getValue(); + assertEquals(inputChar, record.getInputChar()); + assertEquals("A0001", record.getResult()); + } + + @Test + public void testGenerateAutoCode_withPadding() { + // 准备参数 + String ruleCode = "PADDED_CODE"; + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(3L).setCode(ruleCode) + .setPadded(true).setMaxLength(10).setPaddedChar("0").setPaddedMethod(1); + MesMdAutoCodePartDO part1 = new MesMdAutoCodePartDO().setType(MesMdAutoCodePartTypeEnum.FIXED_CHAR.getType()) + .setFixCharacter("IT").setLength(2).setSort(1); + // mock + when(ruleService.getAutoCodeRuleByCode(ruleCode)).thenReturn(rule); + when(partService.getAutoCodePartListByRuleId(3L)).thenReturn(Arrays.asList(part1)); + when(fixedCharStrategy.generate(eq(part1), any(MesMdAutoCodeContext.class))).thenReturn("IT"); + when(recordMapper.selectByResult("00000000IT")).thenReturn(null); + + // 调用 + String result = recordService.generateAutoCode(ruleCode, null); + // 断言:IT 补齐到 10 位,左补 0 + assertEquals("00000000IT", result); + verify(recordMapper).insert(any(MesMdAutoCodeRecordDO.class)); + } + + @Test + public void testGenerateAutoCode_withDatePart() { + // 准备参数 + String ruleCode = "DATE_CODE"; + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(4L).setCode(ruleCode).setPadded(false); + MesMdAutoCodePartDO part1 = new MesMdAutoCodePartDO().setType(MesMdAutoCodePartTypeEnum.DATE.getType()) + .setDateFormat("yyyyMMdd").setLength(8).setSort(1); + MesMdAutoCodePartDO part2 = new MesMdAutoCodePartDO().setType(MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType()) + .setSerialStartNo(1).setSerialStep(1).setLength(4).setSort(2).setCycleFlag(false); + + // mock + when(ruleService.getAutoCodeRuleByCode(ruleCode)).thenReturn(rule); + when(partService.getAutoCodePartListByRuleId(4L)).thenReturn(Arrays.asList(part1, part2)); + when(dateStrategy.generate(eq(part1), any(MesMdAutoCodeContext.class))).thenReturn("20260304"); + when(serialNumberStrategy.generate(eq(part2), any(MesMdAutoCodeContext.class))).thenReturn("0001"); + when(recordMapper.selectByResult("202603040001")).thenReturn(null); + + // 调用 + String result = recordService.generateAutoCode(ruleCode, null); + // 断言:日期 8 位 + 流水号 4 位 = 12 位 + assertEquals(12, result.length()); + assertEquals("202603040001", result); + verify(recordMapper).insert(any(MesMdAutoCodeRecordDO.class)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategyTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategyTest.java new file mode 100644 index 000000000..9ab9f1db5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategyTest.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * {@link MesMdAutoCodeDatePartStrategy} 的单元测试 + * + * @author 芋道源码 + */ +public class MesMdAutoCodeDatePartStrategyTest { + + private final MesMdAutoCodeDatePartStrategy strategy = new MesMdAutoCodeDatePartStrategy(); + + @Test + public void testGenerate_withDefaultFormat() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setDateFormat(null); + MesMdAutoCodeContext context = new MesMdAutoCodeContext(); + + // 调用 + String result = strategy.generate(part, context); + + // 断言:默认格式为 yyyyMMdd,长度为 8 + assertEquals(8, result.length()); + assertTrue(result.matches("\\d{8}")); + } + + @Test + public void testGenerate_withCustomFormat() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setDateFormat("yyyyMM"); + MesMdAutoCodeContext context = new MesMdAutoCodeContext(); + + // 调用 + String result = strategy.generate(part, context); + // 断言:格式为 yyyyMM,长度为 6 + assertEquals(6, result.length()); + assertTrue(result.matches("\\d{6}")); + } + + @Test + public void testGenerate_withTimeFormat() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setDateFormat("HHmmss"); + MesMdAutoCodeContext context = new MesMdAutoCodeContext(); + + // 调用 + String result = strategy.generate(part, context); + // 断言:格式为 HHmmss,长度为 6 + assertEquals(6, result.length()); + assertTrue(result.matches("\\d{6}")); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategyTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategyTest.java new file mode 100644 index 000000000..8662146ec --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategyTest.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link MesMdAutoCodeFixedCharPartStrategy} 的单元测试 + * + * @author 芋道源码 + */ +public class MesMdAutoCodeFixedCharPartStrategyTest { + + private final MesMdAutoCodeFixedCharPartStrategy strategy = new MesMdAutoCodeFixedCharPartStrategy(); + + @Test + public void testGenerate_withFixedChar() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setFixCharacter("ITEM_"); + MesMdAutoCodeContext context = new MesMdAutoCodeContext(); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("ITEM_", result); + } + + @Test + public void testGenerate_withEmptyFixedChar() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setFixCharacter(""); + MesMdAutoCodeContext context = new MesMdAutoCodeContext(); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("", result); + } + + @Test + public void testGenerate_withNullFixedChar() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setFixCharacter(null); + MesMdAutoCodeContext context = new MesMdAutoCodeContext(); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("", result); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategyTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategyTest.java new file mode 100644 index 000000000..a51738157 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategyTest.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link MesMdAutoCodeInputCharPartStrategy} 的单元测试 + * + * @author 芋道源码 + */ +public class MesMdAutoCodeInputCharPartStrategyTest { + + private final MesMdAutoCodeInputCharPartStrategy strategy = new MesMdAutoCodeInputCharPartStrategy(); + + @Test + public void testGenerate_withInputChar() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO(); + MesMdAutoCodeContext context = new MesMdAutoCodeContext().setInputChar("ABC"); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("ABC", result); + } + + @Test + public void testGenerate_withEmptyInputChar() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO(); + MesMdAutoCodeContext context = new MesMdAutoCodeContext().setInputChar(""); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("", result); + } + + @Test + public void testGenerate_withNullInputChar() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO(); + MesMdAutoCodeContext context = new MesMdAutoCodeContext().setInputChar(null); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("", result); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategyTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategyTest.java new file mode 100644 index 000000000..9f2655826 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategyTest.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.iocoder.yudao.framework.test.core.ut.BaseRedisUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import cn.iocoder.yudao.module.mes.dal.redis.md.autocode.MesMdAutoCodeRedisDAO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeCycleMethodEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link MesMdAutoCodeSerialNumberPartStrategy} 的单元测试 + * + * @author 芋道源码 + */ +@Import({MesMdAutoCodeSerialNumberPartStrategy.class, MesMdAutoCodeRedisDAO.class}) +public class MesMdAutoCodeSerialNumberPartStrategyTest extends BaseRedisUnitTest { + + @Resource + private MesMdAutoCodeSerialNumberPartStrategy strategy; + + @Test + public void testGenerate_noCycle() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setLength(4).setSerialStartNo(1).setSerialStep(1).setCycleFlag(false); + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(1L); + MesMdAutoCodeContext context = new MesMdAutoCodeContext().setRule(rule); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("0001", result); + assertEquals(1, context.getSerialNo()); + } + + @Test + public void testGenerate_withCycleByDay() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setLength(4).setSerialStartNo(1).setSerialStep(1) + .setCycleFlag(true).setCycleMethod(MesMdAutoCodeCycleMethodEnum.DAY.getMethod()); + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(2L); + MesMdAutoCodeContext context = new MesMdAutoCodeContext().setRule(rule); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("0001", result); + assertEquals(1, context.getSerialNo()); + } + + @Test + public void testGenerate_withCycleByInputChar() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setLength(4).setSerialStartNo(1).setSerialStep(1) + .setCycleFlag(true).setCycleMethod(MesMdAutoCodeCycleMethodEnum.INPUT_CHAR.getMethod()); + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(3L); + MesMdAutoCodeContext context = new MesMdAutoCodeContext().setRule(rule).setInputChar("A"); + + // 调用 + String result = strategy.generate(part, context); + // 断言 + assertEquals("0001", result); + assertEquals(1, context.getSerialNo()); + } + + @Test + public void testGenerate_withStep() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setLength(4).setSerialStartNo(1).setSerialStep(5).setCycleFlag(false); + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(4L); + MesMdAutoCodeContext context1 = new MesMdAutoCodeContext().setRule(rule); + MesMdAutoCodeContext context2 = new MesMdAutoCodeContext().setRule(rule); + + // 调用 + String result1 = strategy.generate(part, context1); + String result2 = strategy.generate(part, context2); + // 断言 + assertEquals("0001", result1); + assertEquals(1, context1.getSerialNo()); + assertEquals("0006", result2); + assertEquals(6, context2.getSerialNo()); + } + + @Test + public void testGenerate_multipleCallsIncrement() { + // 准备参数 + MesMdAutoCodePartDO part = new MesMdAutoCodePartDO().setLength(4).setSerialStartNo(1).setSerialStep(1).setCycleFlag(false); + MesMdAutoCodeRuleDO rule = new MesMdAutoCodeRuleDO().setId(5L); + MesMdAutoCodeContext context1 = new MesMdAutoCodeContext().setRule(rule); + MesMdAutoCodeContext context2 = new MesMdAutoCodeContext().setRule(rule); + + // 调用 + String result1 = strategy.generate(part, context1); + String result2 = strategy.generate(part, context2); + // 断言 + assertEquals("0001", result1); + assertEquals("0002", result2); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImplTest.java new file mode 100644 index 000000000..f2bb17dc5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImplTest.java @@ -0,0 +1,196 @@ +package cn.iocoder.yudao.module.mes.service.pro.feedback; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +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.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +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.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.itemconsume.MesWmItemConsumeService; +import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService; +import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesProFeedbackServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesProFeedbackServiceImpl.class) +public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesProFeedbackServiceImpl feedbackService; + + @Resource + private MesProFeedbackMapper feedbackMapper; + + @MockitoBean + private MesProWorkOrderService workOrderService; + @MockitoBean + private MesProRouteProcessService routeProcessService; + @MockitoBean + private MesMdWorkstationService workstationService; + @MockitoBean + private MesProTaskService taskService; + @MockitoBean + private MesWmItemConsumeService itemConsumeService; + @MockitoBean + private MesWmProductProduceService productProduceService; + @MockitoBean + private MesWmProductProduceLineService produceLineService; + + @Test + public void testUpdateProFeedbackWhenIpqcFinish_success_withUnqualified() { + // 准备数据:插入一条待检验状态的报工单 + Long taskId = randomLongId(); + Long workOrderId = randomLongId(); + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.UNCHECK.getStatus()); + o.setTaskId(taskId); + o.setWorkOrderId(workOrderId); + o.setFeedbackQuantity(BigDecimal.valueOf(100)); + }); + feedbackMapper.insert(feedback); + + // mock: 产出行(用于 updateTaskAndWorkOrderByFeedback 内的数量聚合) + MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() + .quantity(BigDecimal.valueOf(80)) + .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) + .build(); + MesWmProductProduceLineDO unqualifiedLine = MesWmProductProduceLineDO.builder() + .quantity(BigDecimal.valueOf(20)) + .qualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) + .build(); + when(produceLineService.getProductProduceLineListByFeedbackId(feedback.getId())) + .thenReturn(List.of(qualifiedLine, unqualifiedLine)); + + // 调用 + BigDecimal qualifiedQty = BigDecimal.valueOf(80); + BigDecimal unqualifiedQty = BigDecimal.valueOf(20); + BigDecimal laborScrapQty = BigDecimal.valueOf(5); + BigDecimal materialScrapQty = BigDecimal.valueOf(10); + BigDecimal otherScrapQty = BigDecimal.valueOf(5); + + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), + qualifiedQty, unqualifiedQty, laborScrapQty, materialScrapQty, otherScrapQty); + + // 断言 1:调用了 splitPendingAndFinishProduce + verify(productProduceService).splitPendingAndFinishProduce( + eq(feedback.getId()), eq(qualifiedQty), eq(unqualifiedQty)); + + // 断言 2:报工单状态更新为已完成 + MesProFeedbackDO updatedFeedback = feedbackMapper.selectById(feedback.getId()); + assertEquals(MesProFeedbackStatusEnum.FINISHED.getStatus(), updatedFeedback.getStatus()); + + // 断言 3:数量回写正确 + assertEquals(0, qualifiedQty.compareTo(updatedFeedback.getQualifiedQuantity())); + assertEquals(0, unqualifiedQty.compareTo(updatedFeedback.getUnqualifiedQuantity())); + assertEquals(0, BigDecimal.ZERO.compareTo(updatedFeedback.getUncheckQuantity())); + assertEquals(0, laborScrapQty.compareTo(updatedFeedback.getLaborScrapQuantity())); + assertEquals(0, materialScrapQty.compareTo(updatedFeedback.getMaterialScrapQuantity())); + assertEquals(0, otherScrapQty.compareTo(updatedFeedback.getOtherScrapQuantity())); + + // 断言 4:更新了任务和工单的已生产数量 + // 注意:数量经过 DB 存取后 scale 可能变化,用 any() 匹配 + verify(taskService).updateProducedQuantity(eq(taskId), + any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class)); + verify(workOrderService).updateProducedQuantity(eq(workOrderId), + any(BigDecimal.class)); + } + + @Test + public void testUpdateProFeedbackWhenIpqcFinish_success_allQualified() { + // 准备数据:全部合格 + Long taskId = randomLongId(); + Long workOrderId = randomLongId(); + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.UNCHECK.getStatus()); + o.setTaskId(taskId); + o.setWorkOrderId(workOrderId); + o.setFeedbackQuantity(BigDecimal.valueOf(50)); + }); + feedbackMapper.insert(feedback); + + // mock: 产出行(全部合格) + MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() + .quantity(BigDecimal.valueOf(50)) + .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) + .build(); + when(produceLineService.getProductProduceLineListByFeedbackId(feedback.getId())) + .thenReturn(List.of(qualifiedLine)); + + // 调用 + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), + BigDecimal.valueOf(50), BigDecimal.ZERO, + BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); + + // 断言 1:报工单状态为已完成 + MesProFeedbackDO updatedFeedback = feedbackMapper.selectById(feedback.getId()); + assertEquals(MesProFeedbackStatusEnum.FINISHED.getStatus(), updatedFeedback.getStatus()); + + // 断言 2:合格品数量正确,不合格品和废品为 0 + assertEquals(0, BigDecimal.valueOf(50).compareTo(updatedFeedback.getQualifiedQuantity())); + assertEquals(0, BigDecimal.ZERO.compareTo(updatedFeedback.getUnqualifiedQuantity())); + assertEquals(0, BigDecimal.ZERO.compareTo(updatedFeedback.getLaborScrapQuantity())); + } + + @Test + public void testUpdateProFeedbackWhenIpqcFinish_feedbackNotExists() { + // 调用不存在的 feedbackId,应该抛异常 + Long feedbackId = randomLongId(); + assertThrows(Exception.class, () -> + feedbackService.updateProFeedbackWhenIpqcFinish(feedbackId, + BigDecimal.TEN, BigDecimal.ZERO, + BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); + } + + @Test + public void testUpdateProFeedbackWhenIpqcFinish_feedbackNotUncheck() { + // 准备数据:草稿状态(不是 UNCHECK),应该报错 + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus()); + }); + feedbackMapper.insert(feedback); + + // 调用,应该抛异常 + assertThrows(Exception.class, () -> + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), + BigDecimal.TEN, BigDecimal.ZERO, + BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); + + // 断言:不应该调用任何产出单方法 + verify(productProduceService, never()).splitPendingAndFinishProduce(anyLong(), any(), any()); + } + + @Test + public void testUpdateProFeedbackWhenIpqcFinish_feedbackAlreadyFinished() { + // 准备数据:已完成状态,不能再次完成 + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus()); + }); + feedbackMapper.insert(feedback); + + // 调用,应该抛异常 + assertThrows(Exception.class, () -> + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), + BigDecimal.TEN, BigDecimal.ZERO, + BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java new file mode 100644 index 000000000..98471d337 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java @@ -0,0 +1,214 @@ +package cn.iocoder.yudao.module.mes.service.qc.ipqc; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; +import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesQcIpqcServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesQcIpqcServiceImpl.class) +public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesQcIpqcServiceImpl ipqcService; + + @Resource + private MesQcIpqcMapper ipqcMapper; + + @MockitoBean + private MesQcTemplateItemService templateItemService; + @MockitoBean + private MesQcIpqcLineService ipqcLineService; + @MockitoBean + private MesProWorkOrderService workOrderService; + @MockitoBean + private MesMdWorkstationService workstationService; + @MockitoBean + private MesMdItemService itemService; + @MockitoBean + private MesQcDefectRecordService defectRecordService; + @MockitoBean + private AdminUserApi adminUserApi; + @MockitoBean + private MesProFeedbackService feedbackService; + + @Test + public void testFinishIpqc_writeBack_feedback() { + // 准备数据:插入一条草稿状态的 IPQC 单,来源为报工单(PRO_FEEDBACK=304) + Long sourceDocId = randomLongId(); + BigDecimal qualifiedQty = BigDecimal.valueOf(80); + BigDecimal unqualifiedQty = BigDecimal.valueOf(20); + BigDecimal laborScrapQty = BigDecimal.valueOf(5); + BigDecimal materialScrapQty = BigDecimal.valueOf(10); + BigDecimal otherScrapQty = BigDecimal.valueOf(5); + + MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); // 非空,满足 finishIpqc 的校验 + o.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); + o.setSourceDocId(sourceDocId); + o.setSourceLineId(null); // 报工场景下预留不使用 + o.setQualifiedQuantity(qualifiedQty); + o.setUnqualifiedQuantity(unqualifiedQty); + o.setLaborScrapQuantity(laborScrapQty); + o.setMaterialScrapQuantity(materialScrapQty); + o.setOtherScrapQuantity(otherScrapQty); + }); + ipqcMapper.insert(ipqc); + + // 调用 + ipqcService.finishIpqc(ipqc.getId()); + + // 断言 1:状态更新为已完成 + MesQcIpqcDO updatedIpqc = ipqcMapper.selectById(ipqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIpqc.getStatus()); + + // 断言 2:调用了 feedbackService.completeFeedbackFromIpqc,传递正确参数 + // 注意:数量经过 DB 存取后 scale 可能变化(例如 80 → 80.00),所以用 any() 匹配 + verify(feedbackService).updateProFeedbackWhenIpqcFinish( + eq(sourceDocId), + any(BigDecimal.class), + any(BigDecimal.class), + any(BigDecimal.class), + any(BigDecimal.class), + any(BigDecimal.class)); + } + + @Test + public void testFinishIpqc_writeBack_feedback_withNullQuantities() { + // 准备数据:合格品/不合格品/废品数量为 null 的场景,应该 defaultIfNull 为 0 + Long sourceDocId = randomLongId(); + MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); + o.setSourceDocId(sourceDocId); + o.setSourceLineId(null); + o.setQualifiedQuantity(null); + o.setUnqualifiedQuantity(null); + o.setLaborScrapQuantity(null); + o.setMaterialScrapQuantity(null); + o.setOtherScrapQuantity(null); + }); + ipqcMapper.insert(ipqc); + + // 调用 + ipqcService.finishIpqc(ipqc.getId()); + + // 断言:所有数量参数都是 BigDecimal.ZERO(defaultIfNull 处理) + verify(feedbackService).updateProFeedbackWhenIpqcFinish( + eq(sourceDocId), + eq(BigDecimal.ZERO), + eq(BigDecimal.ZERO), + eq(BigDecimal.ZERO), + eq(BigDecimal.ZERO), + eq(BigDecimal.ZERO)); + } + + @Test + public void testFinishIpqc_writeBack_noSourceDoc() { + // 准备数据:sourceDocType 为空,不需要回写 + MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(null); + o.setSourceDocId(null); + o.setSourceLineId(null); + }); + ipqcMapper.insert(ipqc); + + // 调用 + ipqcService.finishIpqc(ipqc.getId()); + + // 断言 1:状态更新成功 + MesQcIpqcDO updatedIpqc = ipqcMapper.selectById(ipqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIpqc.getStatus()); + + // 断言 2:不应该调用 feedbackService + verify(feedbackService, never()).updateProFeedbackWhenIpqcFinish( + anyLong(), any(), any(), any(), any(), any()); + } + + @Test + public void testFinishIpqc_writeBack_sourceDocTypeDirtyData() { + // 准备数据:sourceDocType 非空但 sourceDocId 为空,应该抛异常 + MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); + o.setSourceDocId(null); // 脏数据 + o.setSourceLineId(null); + }); + ipqcMapper.insert(ipqc); + + // 调用,并断言异常 + assertThrows(IllegalArgumentException.class, () -> ipqcService.finishIpqc(ipqc.getId())); + } + + @Test + public void testFinishIpqc_writeBack_unknownSourceDocType() { + // 准备数据:sourceDocType 无法识别 + MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(99999); // 无法识别的类型 + o.setSourceDocId(randomLongId()); + o.setSourceLineId(null); + }); + ipqcMapper.insert(ipqc); + + // 调用,并断言异常 + assertThrows(IllegalArgumentException.class, () -> ipqcService.finishIpqc(ipqc.getId())); + } + + @Test + public void testFinishIpqc_checkResultEmpty() { + // 准备数据:checkResult 为空,应该报错 + MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(null); // 检测结论为空 + o.setSourceDocType(null); + }); + ipqcMapper.insert(ipqc); + + // 调用,应该抛异常(检测结论必填) + assertThrows(Exception.class, () -> ipqcService.finishIpqc(ipqc.getId())); + } + + @Test + public void testFinishIpqc_notDraftStatus() { + // 准备数据:已完成状态,不能再次完成 + MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.FINISHED.getStatus()); + o.setCheckResult(1); + }); + ipqcMapper.insert(ipqc); + + // 调用,应该抛异常(不是草稿状态) + assertThrows(Exception.class, () -> ipqcService.finishIpqc(ipqc.getId())); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImplTest.java new file mode 100644 index 000000000..64c794cce --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImplTest.java @@ -0,0 +1,203 @@ +package cn.iocoder.yudao.module.mes.service.qc.iqc; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.iqc.MesQcIqcMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import jakarta.annotation.Resource; + +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesQcIqcServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesQcIqcServiceImpl.class) +public class MesQcIqcServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesQcIqcServiceImpl iqcService; + + @Resource + private MesQcIqcMapper iqcMapper; + + @MockitoBean + private MesWmArrivalNoticeService arrivalNoticeService; + @MockitoBean + private MesWmOutsourceReceiptService outsourceReceiptService; + @MockitoBean + private MesQcIqcLineService iqcLineService; + @MockitoBean + private MesQcDefectRecordService defectRecordService; + @MockitoBean + private MesMdVendorService vendorService; + @MockitoBean + private MesMdItemService itemService; + @MockitoBean + private MesQcTemplateItemService templateItemService; + @MockitoBean + private AdminUserApi adminUserApi; + + @Test + public void testFinishIqc_writeBack_arrivalNotice() { + // 准备数据:插入一条草稿状态的 IQC 单,来源为到货通知单 + Long sourceDocId = randomLongId(); + Long sourceLineId = randomLongId(); + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); // 非空,满足 finishIqc 的校验 + o.setSourceDocType(MesBizTypeConstants.WM_ARRIVAL_NOTICE); + o.setSourceDocId(sourceDocId); + o.setSourceLineId(sourceLineId); + o.setQualifiedQuantity(BigDecimal.valueOf(100)); + o.setUnqualifiedQuantity(BigDecimal.ZERO); + }); + iqcMapper.insert(iqc); + + // 调用 + iqcService.finishIqc(iqc.getId()); + + // 断言:验证状态更新为已完成 + MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus()); + // 断言:验证回写到货通知单(参数使用 any 避免 BigDecimal 精度问题) + verify(arrivalNoticeService).updateArrivalNoticeWhenIqcFinish( + eq(sourceDocId), eq(sourceLineId), eq(iqc.getId()), any(BigDecimal.class)); + // 断言:不应该调用外协入库单的回写 + verify(outsourceReceiptService, never()).updateOutsourceReceiptWhenIqcFinish( + anyLong(), anyLong(), anyLong(), any(), any()); + } + + @Test + public void testFinishIqc_writeBack_outsourceReceipt() { + // 准备数据:插入一条草稿状态的 IQC 单,来源为外协入库单 + Long sourceDocId = randomLongId(); + Long sourceLineId = randomLongId(); + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(MesBizTypeConstants.WM_OUTSOURCE_RECPT); + o.setSourceDocId(sourceDocId); + o.setSourceLineId(sourceLineId); + o.setQualifiedQuantity(BigDecimal.valueOf(80)); + o.setUnqualifiedQuantity(BigDecimal.valueOf(20)); + }); + iqcMapper.insert(iqc); + + // 调用 + iqcService.finishIqc(iqc.getId()); + + // 断言:验证状态更新为已完成 + MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus()); + // 断言:验证回写外协入库单(参数使用 any 避免 BigDecimal 精度问题) + verify(outsourceReceiptService).updateOutsourceReceiptWhenIqcFinish( + eq(sourceDocId), eq(sourceLineId), eq(iqc.getId()), any(BigDecimal.class), any(BigDecimal.class)); + // 断言:不应该调用到货通知单的回写 + verify(arrivalNoticeService, never()).updateArrivalNoticeWhenIqcFinish( + anyLong(), anyLong(), anyLong(), any()); + } + + @Test + public void testFinishIqc_writeBack_noSourceDoc() { + // 准备数据:sourceDocType 为空,不需要回写 + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(null); + o.setSourceDocId(null); + o.setSourceLineId(null); + }); + iqcMapper.insert(iqc); + + // 调用 + iqcService.finishIqc(iqc.getId()); + + // 断言:验证状态更新为已完成 + MesQcIqcDO updatedIqc = iqcMapper.selectById(iqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIqc.getStatus()); + // 断言:不应该调用任何回写 + verify(arrivalNoticeService, never()).updateArrivalNoticeWhenIqcFinish( + anyLong(), anyLong(), anyLong(), any()); + verify(outsourceReceiptService, never()).updateOutsourceReceiptWhenIqcFinish( + anyLong(), anyLong(), anyLong(), any(), any()); + } + + @Test + public void testFinishIqc_writeBack_sourceDocTypeDirtyData() { + // 准备数据:sourceDocType 非空但 sourceLineId 为空,应该抛异常 + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(MesBizTypeConstants.WM_ARRIVAL_NOTICE); + o.setSourceDocId(randomLongId()); + o.setSourceLineId(null); // 脏数据 + }); + iqcMapper.insert(iqc); + + // 调用,并断言异常 + assertThrows(IllegalArgumentException.class, () -> iqcService.finishIqc(iqc.getId())); + } + + @Test + public void testFinishIqc_writeBack_unknownSourceDocType() { + // 准备数据:sourceDocType 无法识别 + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(99999); // 无法识别的类型 + o.setSourceDocId(randomLongId()); + o.setSourceLineId(randomLongId()); + }); + iqcMapper.insert(iqc); + + // 调用,并断言异常 + assertThrows(IllegalArgumentException.class, () -> iqcService.finishIqc(iqc.getId())); + } + + @Test + public void testFinishIqc_checkResultEmpty() { + // 准备数据:checkResult 为空,应该报错 + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(null); // 检测结论为空 + o.setSourceDocType(null); + }); + iqcMapper.insert(iqc); + + // 调用,应该抛异常(检测结论必填) + assertThrows(Exception.class, () -> iqcService.finishIqc(iqc.getId())); + } + + @Test + public void testFinishIqc_notDraftStatus() { + // 准备数据:已完成状态,不能再次完成 + MesQcIqcDO iqc = randomPojo(MesQcIqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.FINISHED.getStatus()); + o.setCheckResult(1); + }); + iqcMapper.insert(iqc); + + // 调用,应该抛异常(不是草稿状态) + assertThrows(Exception.class, () -> iqcService.finishIqc(iqc.getId())); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java new file mode 100644 index 000000000..19b18ccb0 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java @@ -0,0 +1,200 @@ +package cn.iocoder.yudao.module.mes.service.qc.oqc; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService; +import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +/** + * {@link MesQcOqcServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(MesQcOqcServiceImpl.class) +public class MesQcOqcServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesQcOqcServiceImpl oqcService; + + @Resource + private MesQcOqcMapper oqcMapper; + + @MockitoBean + private MesWmProductSalesLineService productSalesLineService; + @MockitoBean + private MesWmProductSalesService productSalesService; + @MockitoBean + private MesQcOqcLineService oqcLineService; + @MockitoBean + private MesMdClientService clientService; + @MockitoBean + private MesMdItemService itemService; + @MockitoBean + private MesQcTemplateItemService templateItemService; + @MockitoBean + private MesQcDefectRecordService defectRecordService; + @MockitoBean + private AdminUserApi adminUserApi; + + @Test + public void testFinishOqc_writeBack_productSales() { + // 准备数据:插入一条草稿状态的 OQC 单,来源为销售出库单 + Long sourceLineId = randomLongId(); + Integer checkResult = 1; + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES); + o.setSourceLineId(sourceLineId); + o.setCheckResult(checkResult); + }); + oqcMapper.insert(oqc); + + // 调用 + oqcService.finishOqc(oqc.getId()); + + // 断言:验证状态更新为已完成 + MesQcOqcDO updatedOqc = oqcMapper.selectById(oqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedOqc.getStatus()); + // 断言:验证回写销售出库单行 + verify(productSalesLineService).updateProductSalesLineWhenOqcFinish( + eq(sourceLineId), eq(oqc.getId()), eq(checkResult)); + } + + @Test + public void testFinishOqc_writeBack_noSourceDoc() { + // 准备数据:sourceDocType 为空,不需要回写 + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(null); + o.setSourceLineId(null); + }); + oqcMapper.insert(oqc); + + // 调用 + oqcService.finishOqc(oqc.getId()); + + // 断言:验证状态更新为已完成 + MesQcOqcDO updatedOqc = oqcMapper.selectById(oqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedOqc.getStatus()); + // 断言:不应该调用任何回写 + verify(productSalesLineService, never()).updateProductSalesLineWhenOqcFinish( + anyLong(), anyLong(), anyInt()); + } + + @Test + public void testFinishOqc_writeBack_sourceDocTypeDirtyData() { + // 准备数据:sourceDocType 非空但 sourceLineId 为空,应该抛异常 + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES); + o.setSourceLineId(null); // 脏数据 + }); + oqcMapper.insert(oqc); + + // 调用,并断言异常 + assertThrows(IllegalArgumentException.class, () -> oqcService.finishOqc(oqc.getId())); + } + + @Test + public void testFinishOqc_writeBack_unknownSourceDocType() { + // 准备数据:sourceDocType 无法识别 + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(1); + o.setSourceDocType(99999); // 无法识别的类型 + o.setSourceLineId(randomLongId()); + }); + oqcMapper.insert(oqc); + + // 调用,并断言异常 + assertThrows(IllegalArgumentException.class, () -> oqcService.finishOqc(oqc.getId())); + } + + @Test + public void testFinishOqc_notExists() { + // 准备参数 + Long oqcId = randomLongId(); + + // 调用,并断言异常 + assertServiceException(() -> oqcService.finishOqc(oqcId), QC_OQC_NOT_EXISTS); + } + + @Test + public void testFinishOqc_statusNotDraft() { + // 准备参数:状态为已完成 + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.FINISHED.getStatus()); + }); + oqcMapper.insert(oqc); + + // 调用,并断言异常 + assertServiceException(() -> oqcService.finishOqc(oqc.getId()), QC_OQC_NOT_PREPARE); + } + + @Test + public void testFinishOqc_checkResultEmpty() { + // 准备数据:checkResult 为空,应该报错 + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setCheckResult(null); // 检测结论为空 + o.setSourceDocType(null); + }); + oqcMapper.insert(oqc); + + // 调用,应该抛异常(检测结论必填) + assertServiceException(() -> oqcService.finishOqc(oqc.getId()), QC_OQC_CHECK_RESULT_EMPTY); + } + + @Test + public void testDeleteOqc_success() { + // 准备数据:草稿状态 + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + }); + oqcMapper.insert(oqc); + + // 调用 + oqcService.deleteOqc(oqc.getId()); + + // 断言:已删除 + assertNull(oqcMapper.selectById(oqc.getId())); + } + + @Test + public void testDeleteOqc_notExists() { + assertServiceException(() -> oqcService.deleteOqc(randomLongId()), QC_OQC_NOT_EXISTS); + } + + @Test + public void testDeleteOqc_statusNotDraft() { + MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.FINISHED.getStatus()); + }); + oqcMapper.insert(oqc); + + assertServiceException(() -> oqcService.deleteOqc(oqc.getId()), QC_OQC_NOT_PREPARE); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImplTest.java new file mode 100644 index 000000000..b7139522a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImplTest.java @@ -0,0 +1,162 @@ +package cn.iocoder.yudao.module.mes.service.qc.rqc; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc.MesQcRqcMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueLineService; +import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesLineService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.QC_RQC_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.QC_RQC_NOT_PREPARE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +/** + * {@link MesQcRqcServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(MesQcRqcServiceImpl.class) +public class MesQcRqcServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesQcRqcServiceImpl rqcService; + + @Resource + private MesQcRqcMapper rqcMapper; + + @MockitoBean + private MesWmReturnIssueLineService returnIssueLineService; + @MockitoBean + private MesWmReturnSalesLineService returnSalesLineService; + @MockitoBean + private MesQcRqcLineService rqcLineService; + @MockitoBean + private MesMdItemService itemService; + @MockitoBean + private MesQcTemplateItemService templateItemService; + @MockitoBean + private MesQcDefectRecordService defectRecordService; + @MockitoBean + private AdminUserApi adminUserApi; + + @Test + public void testFinishRqc_successWithReturnIssue() { + // 准备参数 + Long sourceLineId = randomLongId(); + Long sourceDocId = randomLongId(); + Integer checkResult = 1; + BigDecimal qualifiedQty = new BigDecimal("80"); + BigDecimal unqualifiedQty = new BigDecimal("20"); + + // mock 数据 + MesQcRqcDO rqc = randomPojo(MesQcRqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setSourceDocType(MesBizTypeConstants.WM_RETURN_ISSUE); + o.setSourceDocId(sourceDocId); + o.setSourceLineId(sourceLineId); + o.setCheckResult(checkResult); + // 设置数量通过 finishRqc 的数量校验:合格 + 不合格 = 检测数量 + o.setCheckQuantity(new BigDecimal("100")); + o.setQualifiedQuantity(qualifiedQty); + o.setUnqualifiedQuantity(unqualifiedQty); + }); + rqcMapper.insert(rqc); + + // 调用 + rqcService.finishRqc(rqc.getId()); + + // 断言:验证状态更新 + MesQcRqcDO updatedRqc = rqcMapper.selectById(rqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedRqc.getStatus()); + + // 断言:验证回写调用生产退料(含拆分参数) + verify(returnIssueLineService).updateReturnIssueLineWhenRqcFinish( + eq(sourceLineId), eq(sourceDocId), eq(checkResult), + argThat(v -> v.compareTo(qualifiedQty) == 0), + argThat(v -> v.compareTo(unqualifiedQty) == 0)); + // 断言:未调用销售退货 + verify(returnSalesLineService, never()).updateReturnSalesLineWhenRqcFinish( + anyLong(), anyLong(), anyInt(), any(BigDecimal.class), any(BigDecimal.class)); + } + + @Test + public void testFinishRqc_successWithReturnSales() { + // 准备参数 + Long sourceLineId = randomLongId(); + Long sourceDocId = randomLongId(); + Integer checkResult = 1; + BigDecimal qualifiedQty = new BigDecimal("90"); + BigDecimal unqualifiedQty = new BigDecimal("10"); + + // mock 数据 + MesQcRqcDO rqc = randomPojo(MesQcRqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); + o.setSourceDocType(MesBizTypeConstants.WM_RETURN_SALES); + o.setSourceDocId(sourceDocId); + o.setSourceLineId(sourceLineId); + o.setCheckResult(checkResult); + // 设置数量通过 finishRqc 的数量校验:合格 + 不合格 = 检测数量 + o.setCheckQuantity(new BigDecimal("100")); + o.setQualifiedQuantity(qualifiedQty); + o.setUnqualifiedQuantity(unqualifiedQty); + }); + rqcMapper.insert(rqc); + + // 调用 + rqcService.finishRqc(rqc.getId()); + + // 断言:验证状态更新 + MesQcRqcDO updatedRqc = rqcMapper.selectById(rqc.getId()); + assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedRqc.getStatus()); + + // 断言:验证回写调用销售退货(含拆分参数) + verify(returnSalesLineService).updateReturnSalesLineWhenRqcFinish( + eq(sourceLineId), eq(sourceDocId), eq(checkResult), + argThat(v -> v.compareTo(qualifiedQty) == 0), + argThat(v -> v.compareTo(unqualifiedQty) == 0)); + // 断言:未调用生产退料 + verify(returnIssueLineService, never()).updateReturnIssueLineWhenRqcFinish( + anyLong(), anyLong(), anyInt(), any(BigDecimal.class), any(BigDecimal.class)); + } + + @Test + public void testFinishRqc_notExists() { + // 准备参数 + Long rqcId = randomLongId(); + + // 调用,并断言异常 + assertServiceException(() -> rqcService.finishRqc(rqcId), QC_RQC_NOT_EXISTS); + } + + @Test + public void testFinishRqc_statusNotDraft() { + // 准备参数 + // mock 数据:状态为已完成 + MesQcRqcDO rqc = randomPojo(MesQcRqcDO.class, o -> { + o.setStatus(MesQcStatusEnum.FINISHED.getStatus()); + }); + rqcMapper.insert(rqc); + + // 调用,并断言异常 + assertServiceException(() -> rqcService.finishRqc(rqc.getId()), QC_RQC_NOT_PREPARE); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImplTest.java new file mode 100644 index 000000000..a742b4d6c --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImplTest.java @@ -0,0 +1,149 @@ +package cn.iocoder.yudao.module.mes.service.wm.arrivalnotice; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import jakarta.annotation.Resource; + +import java.math.BigDecimal; +import java.util.Arrays; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +/** + * {@link MesWmArrivalNoticeServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesWmArrivalNoticeServiceImpl.class) +public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmArrivalNoticeServiceImpl arrivalNoticeService; + + @Resource + private MesWmArrivalNoticeMapper arrivalNoticeMapper; + + @MockitoBean + private MesWmArrivalNoticeLineService arrivalNoticeLineService; + + @Test + public void testUpdateArrivalNoticeWhenIqcFinish_success_allLinesChecked() { + // mock 数据:插入一条待质检的到货通知单 + MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> { + o.setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus()); + }); + arrivalNoticeMapper.insert(notice); + // 准备参数 + Long noticeId = notice.getId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(100); + + // mock 行服务方法:所有需检行都已完成(iqcId 不为空) + MesWmArrivalNoticeLineDO line1 = randomPojo(MesWmArrivalNoticeLineDO.class, o -> { + o.setNoticeId(noticeId); + o.setIqcCheckFlag(true); + o.setIqcId(iqcId); // 已检完 + }); + MesWmArrivalNoticeLineDO line2 = randomPojo(MesWmArrivalNoticeLineDO.class, o -> { + o.setNoticeId(noticeId); + o.setIqcCheckFlag(false); // 不需要检验 + o.setIqcId(null); + }); + when(arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(eq(noticeId))) + .thenReturn(Arrays.asList(line1, line2)); + + // 调用 + arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(noticeId, lineId, iqcId, qualifiedQuantity); + + // 断言:行回写被调用 + verify(arrivalNoticeLineService).updateArrivalNoticeLineWhenIqcFinish(eq(lineId), eq(iqcId), eq(qualifiedQuantity)); + // 断言:主表状态更新为待入库 + MesWmArrivalNoticeDO updatedNotice = arrivalNoticeMapper.selectById(noticeId); + assertEquals(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus(), updatedNotice.getStatus()); + } + + @Test + public void testUpdateArrivalNoticeWhenIqcFinish_success_hasUncheckedLines() { + // mock 数据:插入一条待质检的到货通知单 + MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> { + o.setStatus(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus()); + }); + arrivalNoticeMapper.insert(notice); + // 准备参数 + Long noticeId = notice.getId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(50); + + // mock 行服务方法:还有未完成的需检行 + MesWmArrivalNoticeLineDO line1 = randomPojo(MesWmArrivalNoticeLineDO.class, o -> { + o.setNoticeId(noticeId); + o.setIqcCheckFlag(true); + o.setIqcId(iqcId); // 已检完 + }); + MesWmArrivalNoticeLineDO line2 = randomPojo(MesWmArrivalNoticeLineDO.class, o -> { + o.setNoticeId(noticeId); + o.setIqcCheckFlag(true); + o.setIqcId(null); // 还未检验 + }); + when(arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(eq(noticeId))) + .thenReturn(Arrays.asList(line1, line2)); + + // 调用 + arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(noticeId, lineId, iqcId, qualifiedQuantity); + + // 断言:行回写被调用 + verify(arrivalNoticeLineService).updateArrivalNoticeLineWhenIqcFinish(eq(lineId), eq(iqcId), eq(qualifiedQuantity)); + // 断言:主表状态不变,仍然是待质检 + MesWmArrivalNoticeDO updatedNotice = arrivalNoticeMapper.selectById(noticeId); + assertEquals(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus(), updatedNotice.getStatus()); + } + + @Test + public void testUpdateArrivalNoticeWhenIqcFinish_noticeNotExists() { + // 准备参数 + Long noticeId = randomLongId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(100); + + // 调用,并断言异常 + assertServiceException( + () -> arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(noticeId, lineId, iqcId, qualifiedQuantity), + WM_ARRIVAL_NOTICE_NOT_EXISTS); + } + + @Test + public void testUpdateArrivalNoticeWhenIqcFinish_statusNotPendingQc() { + // mock 数据:插入一条草稿状态的到货通知单(非待质检) + MesWmArrivalNoticeDO notice = randomPojo(MesWmArrivalNoticeDO.class, o -> { + o.setStatus(MesWmArrivalNoticeStatusEnum.PREPARE.getStatus()); + }); + arrivalNoticeMapper.insert(notice); + // 准备参数 + Long noticeId = notice.getId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(100); + + // 调用,并断言异常 + assertServiceException( + () -> arrivalNoticeService.updateArrivalNoticeWhenIqcFinish(noticeId, lineId, iqcId, qualifiedQuantity), + WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_QC); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImplTest.java new file mode 100644 index 000000000..f53321dd7 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImplTest.java @@ -0,0 +1,407 @@ +package cn.iocoder.yudao.module.mes.service.wm.batch; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; +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.dal.mysql.wm.batch.MesWmBatchMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume.MesWmItemConsumeDetailMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume.MesWmItemConsumeMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceDetailMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceLineMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceMapper; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemBatchConfigService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link MesWmBatchServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesWmBatchServiceImpl.class) +public class MesWmBatchServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmBatchServiceImpl batchService; + + @Resource + private MesWmBatchMapper batchMapper; + + @Resource + private MesWmItemConsumeMapper consumeMapper; + @Resource + private MesWmItemConsumeDetailMapper consumeDetailMapper; + @Resource + private MesProFeedbackMapper feedbackMapper; + @Resource + private MesWmProductProduceMapper produceMapper; + @Resource + private MesWmProductProduceLineMapper produceLineMapper; + @Resource + private MesWmProductProduceDetailMapper produceDetailMapper; + + @MockitoBean + private MesMdItemService itemService; + @MockitoBean + private MesMdItemBatchConfigService itemBatchConfigService; + @MockitoBean + private MesMdAutoCodeRecordService autoCodeRecordService; + @MockitoBean + private MesWmBarcodeService barcodeService; + + // ==================== 向前追溯 ==================== + + @Test + public void testGetForwardBatchList_nullCode() { + // 传入 null code,应返回空列表(不抛异常) + List result = batchService.getForwardBatchList(null); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + public void testGetForwardBatchList_noResults() { + // 传入一个不存在的批次号,XML 查询返回空(因为关联表无数据) + List result = batchService.getForwardBatchList("NOT_EXIST_CODE"); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + // ==================== 向后追溯 ==================== + + @Test + public void testGetBackwardBatchList_nullCode() { + // 传入 null code,应返回空列表(不抛异常) + List result = batchService.getBackwardBatchList(null); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + @Test + public void testGetBackwardBatchList_noResults() { + // 传入一个不存在的批次号,XML 查询返回空 + List result = batchService.getBackwardBatchList("NOT_EXIST_CODE"); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + // ==================== 循环检测 ==================== + + @Test + public void testForwardBatchList_sameCodeDoesNotRecurse() { + // 验证:传入相同 code 多次调用不会 StackOverflow + // 由于数据库中没有环路数据,这里主要验证 visited set 的 null + 空数据安全 + List result = batchService.getForwardBatchList("SAME_CODE"); + assertNotNull(result); + assertTrue(result.isEmpty()); + + // 二次调用同一个 code,不应有任何异常 + List result2 = batchService.getForwardBatchList("SAME_CODE"); + assertNotNull(result2); + assertTrue(result2.isEmpty()); + } + + @Test + public void testBackwardBatchList_sameCodeDoesNotRecurse() { + // 验证向后追溯的 visited set 安全 + List result = batchService.getBackwardBatchList("SAME_CODE"); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + // ==================== selectFirst ==================== + + @Test + public void testSelectFirst_noMatch() { + // 查询不存在的 itemId,应返回 null + MesWmBatchDO query = MesWmBatchDO.builder().itemId(randomLongId()).build(); + MesWmBatchDO result = batchMapper.selectFirst(query); + assertNull(result); + } + + @Test + public void testSelectFirst_returnsSmallestId() { + // 准备数据:插入两条相同条件的批次 + Long itemId = randomLongId(); + MesWmBatchDO batch1 = MesWmBatchDO.builder() + .itemId(itemId).code("BATCH_001").build(); + MesWmBatchDO batch2 = MesWmBatchDO.builder() + .itemId(itemId).code("BATCH_002").build(); + batchMapper.insert(batch1); + batchMapper.insert(batch2); + + // 查询 + MesWmBatchDO query = MesWmBatchDO.builder().itemId(itemId).build(); + MesWmBatchDO result = batchMapper.selectFirst(query); + + // 断言:返回 ID 最小的 + assertNotNull(result); + assertEquals(batch1.getId(), result.getId()); + assertEquals("BATCH_001", result.getCode()); + } + + @Test + public void testSelectFirst_nullFieldMatching() { + // 准备数据:一条有 vendorId,一条没有 vendorId + Long itemId = randomLongId(); + Long vendorId = randomLongId(); + + MesWmBatchDO batchWithVendor = MesWmBatchDO.builder() + .itemId(itemId).code("BATCH_WITH_V").vendorId(vendorId).build(); + MesWmBatchDO batchWithoutVendor = MesWmBatchDO.builder() + .itemId(itemId).code("BATCH_NO_V").build(); + batchMapper.insert(batchWithVendor); + batchMapper.insert(batchWithoutVendor); + + // 查询:vendorId 为 null -> 应该只匹配 vendorId IS NULL 的记录 + MesWmBatchDO query = MesWmBatchDO.builder().itemId(itemId).build(); + MesWmBatchDO result = batchMapper.selectFirst(query); + + assertNotNull(result); + assertEquals("BATCH_NO_V", result.getCode()); + assertNull(result.getVendorId()); + } + + @Test + public void testSelectFirst_withVendorId() { + // 准备数据 + Long itemId = randomLongId(); + Long vendorId = randomLongId(); + + MesWmBatchDO batchWithVendor = MesWmBatchDO.builder() + .itemId(itemId).code("BATCH_V1").vendorId(vendorId).build(); + MesWmBatchDO batchWithoutVendor = MesWmBatchDO.builder() + .itemId(itemId).code("BATCH_NV").build(); + batchMapper.insert(batchWithVendor); + batchMapper.insert(batchWithoutVendor); + + // 查询:指定 vendorId -> 只匹配有 vendorId 的 + MesWmBatchDO query = MesWmBatchDO.builder().itemId(itemId).vendorId(vendorId).build(); + MesWmBatchDO result = batchMapper.selectFirst(query); + + assertNotNull(result); + assertEquals("BATCH_V1", result.getCode()); + assertEquals(vendorId, result.getVendorId()); + } + + // ==================== selectByCode ==================== + + @Test + public void testSelectByCode() { + // 准备数据 + MesWmBatchDO batch = MesWmBatchDO.builder() + .itemId(randomLongId()).code("TEST_CODE_001").build(); + batchMapper.insert(batch); + + // 查询 + MesWmBatchDO result = batchMapper.selectByCode("TEST_CODE_001"); + assertNotNull(result); + assertEquals(batch.getId(), result.getId()); + + // 查询不存在的 + MesWmBatchDO notFound = batchMapper.selectByCode("NOT_EXIST"); + assertNull(notFound); + } + + // ==================== 向前追溯(集成测试)==================== + + /** + * 向前追溯集成测试:构造完整链路数据 + * 链路:消耗明细(icd, batchCode=RAW_BATCH) → 消耗单(ic) → 报工(pf) → 入库单(pp) → 入库行(ppl, batchCode=PRODUCT_BATCH) + * 预期:查 RAW_BATCH 能找到 PRODUCT_BATCH + */ + @Test + public void testSelectListByForward_withData() { + // 准备:公共 ID + Long workOrderId = randomLongId(); + Long rawItemId = randomLongId(); + Long productItemId = randomLongId(); + Long productBatchId = randomLongId(); + LocalDateTime now = LocalDateTime.now(); + + // 1. 报工记录 + MesProFeedbackDO feedback = MesProFeedbackDO.builder() + .workOrderId(workOrderId).itemId(productItemId).build(); + feedbackMapper.insert(feedback); + + // 2. 消耗单 + MesWmItemConsumeDO consume = MesWmItemConsumeDO.builder() + .workOrderId(workOrderId).taskId(randomLongId()).workstationId(randomLongId()) + .processId(randomLongId()).feedbackId(feedback.getId()).consumeDate(now).build(); + consumeMapper.insert(consume); + + // 3. 消耗明细(关联原材料批次 RAW_BATCH) + MesWmItemConsumeDetailDO consumeDetail = MesWmItemConsumeDetailDO.builder() + .consumeId(consume.getId()).lineId(randomLongId()).itemId(rawItemId) + .quantity(BigDecimal.TEN).batchCode("RAW_BATCH") + .warehouseId(randomLongId()).locationId(randomLongId()).areaId(randomLongId()).build(); + consumeDetailMapper.insert(consumeDetail); + + // 4. 生产入库单 + MesWmProductProduceDO produce = MesWmProductProduceDO.builder() + .workOrderId(workOrderId).build(); + produceMapper.insert(produce); + + // 5. 入库行(关联成品批次 PRODUCT_BATCH) + MesWmProductProduceLineDO produceLine = MesWmProductProduceLineDO.builder() + .produceId(produce.getId()).itemId(productItemId) + .batchId(productBatchId).batchCode("PRODUCT_BATCH").build(); + produceLineMapper.insert(produceLine); + + // 执行向前追溯 + List result = batchMapper.selectListByForward("RAW_BATCH"); + + // 断言 + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("PRODUCT_BATCH", result.get(0).getCode()); + assertEquals(productBatchId, result.get(0).getId()); + assertEquals(workOrderId, result.get(0).getWorkOrderId()); + assertEquals(productItemId, result.get(0).getItemId()); + } + + /** + * 向前追溯:已删除的消耗明细应被过滤(icd.deleted = 1) + */ + @Test + public void testSelectListByForward_deletedDataFiltered() { + Long workOrderId = randomLongId(); + LocalDateTime now = LocalDateTime.now(); + + // 1. 报工记录 + MesProFeedbackDO feedback = MesProFeedbackDO.builder() + .workOrderId(workOrderId).itemId(randomLongId()).build(); + feedbackMapper.insert(feedback); + + // 2. 消耗单 + MesWmItemConsumeDO consume = MesWmItemConsumeDO.builder() + .workOrderId(workOrderId).taskId(randomLongId()).workstationId(randomLongId()) + .processId(randomLongId()).feedbackId(feedback.getId()).consumeDate(now).build(); + consumeMapper.insert(consume); + + // 3. 消耗明细(逻辑删除) + MesWmItemConsumeDetailDO consumeDetail = MesWmItemConsumeDetailDO.builder() + .consumeId(consume.getId()).lineId(randomLongId()).itemId(randomLongId()) + .quantity(BigDecimal.TEN).batchCode("RAW_DEL_TEST") + .warehouseId(randomLongId()).locationId(randomLongId()).areaId(randomLongId()).build(); + consumeDetailMapper.insert(consumeDetail); + consumeDetailMapper.deleteById(consumeDetail.getId()); // 逻辑删除消耗明细 + + // 4. 生产入库单 + 入库行 + MesWmProductProduceDO produce = MesWmProductProduceDO.builder() + .workOrderId(workOrderId).build(); + produceMapper.insert(produce); + MesWmProductProduceLineDO produceLine = MesWmProductProduceLineDO.builder() + .produceId(produce.getId()).itemId(randomLongId()) + .batchId(randomLongId()).batchCode("PRODUCT_DEL_TEST").build(); + produceLineMapper.insert(produceLine); + + // 执行:消耗明细已删除,应该追溯不到 + List result = batchMapper.selectListByForward("RAW_DEL_TEST"); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + + // ==================== 向后追溯(集成测试)==================== + + /** + * 向后追溯集成测试:构造完整链路数据 + * 链路:入库明细(ppd, batchCode=PRODUCT_BATCH) → 入库单(pp) → 消耗单(ic) → 消耗明细(icd, batchCode=RAW_BATCH) + * 预期:查 PRODUCT_BATCH 能找到 RAW_BATCH + */ + @Test + public void testSelectListByBackward_withData() { + Long workOrderId = randomLongId(); + Long rawItemId = randomLongId(); + Long rawBatchId = randomLongId(); + LocalDateTime now = LocalDateTime.now(); + + // 1. 生产入库单 + MesWmProductProduceDO produce = MesWmProductProduceDO.builder() + .workOrderId(workOrderId).build(); + produceMapper.insert(produce); + + // 2. 入库明细(关联成品批次 PRODUCT_BACK_BATCH) + MesWmProductProduceDetailDO produceDetail = MesWmProductProduceDetailDO.builder() + .produceId(produce.getId()).itemId(randomLongId()) + .batchCode("PRODUCT_BACK_BATCH").build(); + produceDetailMapper.insert(produceDetail); + + // 3. 消耗单 + MesWmItemConsumeDO consume = MesWmItemConsumeDO.builder() + .workOrderId(workOrderId).taskId(randomLongId()).workstationId(randomLongId()) + .processId(randomLongId()).feedbackId(randomLongId()).consumeDate(now).build(); + consumeMapper.insert(consume); + + // 4. 消耗明细(关联原材料批次 RAW_BACK_BATCH) + MesWmItemConsumeDetailDO consumeDetail = MesWmItemConsumeDetailDO.builder() + .consumeId(consume.getId()).lineId(randomLongId()).itemId(rawItemId) + .quantity(BigDecimal.ONE).batchId(rawBatchId).batchCode("RAW_BACK_BATCH") + .warehouseId(randomLongId()).locationId(randomLongId()).areaId(randomLongId()).build(); + consumeDetailMapper.insert(consumeDetail); + + // 执行向后追溯 + List result = batchMapper.selectListByBackward("PRODUCT_BACK_BATCH"); + + // 断言 + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("RAW_BACK_BATCH", result.get(0).getCode()); + assertEquals(rawBatchId, result.get(0).getId()); + assertEquals(workOrderId, result.get(0).getWorkOrderId()); + assertEquals(rawItemId, result.get(0).getItemId()); + } + + /** + * 向后追溯:消耗明细 batchCode 为 NULL 的应被过滤 + */ + @Test + public void testSelectListByBackward_nullBatchCodeFiltered() { + Long workOrderId = randomLongId(); + LocalDateTime now = LocalDateTime.now(); + + // 生产入库单 + 入库明细 + MesWmProductProduceDO produce = MesWmProductProduceDO.builder() + .workOrderId(workOrderId).build(); + produceMapper.insert(produce); + MesWmProductProduceDetailDO produceDetail = MesWmProductProduceDetailDO.builder() + .produceId(produce.getId()).itemId(randomLongId()) + .batchCode("PRODUCT_NULL_TEST").build(); + produceDetailMapper.insert(produceDetail); + + // 消耗单 + 消耗明细(batchCode 为 null) + MesWmItemConsumeDO consume = MesWmItemConsumeDO.builder() + .workOrderId(workOrderId).taskId(randomLongId()).workstationId(randomLongId()) + .processId(randomLongId()).feedbackId(randomLongId()).consumeDate(now).build(); + consumeMapper.insert(consume); + MesWmItemConsumeDetailDO consumeDetail = MesWmItemConsumeDetailDO.builder() + .consumeId(consume.getId()).lineId(randomLongId()).itemId(randomLongId()) + .quantity(BigDecimal.ONE).batchCode(null) // 无批次 + .warehouseId(randomLongId()).locationId(randomLongId()).areaId(randomLongId()).build(); + consumeDetailMapper.insert(consumeDetail); + + // 执行:应过滤掉 batchCode IS NULL 的消耗明细 + List result = batchMapper.selectListByBackward("PRODUCT_NULL_TEST"); + assertNotNull(result); + assertTrue(result.isEmpty()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeServiceImplTest.java new file mode 100644 index 000000000..c5e2e09bf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemconsume/MesWmItemConsumeServiceImplTest.java @@ -0,0 +1,525 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemconsume; + +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemconsume.MesWmItemConsumeMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemConsumeStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductBomService; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_FEEDBACK_ROUTE_PROCESS_INVALID; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_ROUTE_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.*; + +/** + * {@link MesWmItemConsumeServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesWmItemConsumeServiceImpl.class) +public class MesWmItemConsumeServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmItemConsumeServiceImpl itemConsumeService; + + @Resource + private MesWmItemConsumeMapper itemConsumeMapper; + + @MockitoBean + private MesWmItemConsumeLineService itemConsumeLineService; + @MockitoBean + private MesWmItemConsumeDetailService itemConsumeDetailService; + @MockitoBean + private MesProRouteProductBomService routeProductBomService; + @MockitoBean + private MesProRouteService routeService; + @MockitoBean + private MesWmTransactionService wmTransactionService; + @MockitoBean + private MesWmWarehouseService warehouseService; + @MockitoBean + private MesWmWarehouseLocationService locationService; + @MockitoBean + private MesWmWarehouseAreaService areaService; + @MockitoBean + private MesWmMaterialStockService materialStockService; + + // ========== 公共 mock 数据 ========== + + private static final Long WAREHOUSE_ID = 100L; + private static final Long LOCATION_ID = 200L; + private static final Long AREA_ID = 300L; + + private MesWmWarehouseDO virtualWarehouse; + private MesWmWarehouseLocationDO virtualLocation; + private MesWmWarehouseAreaDO virtualArea; + + @BeforeEach + public void setUp() { + virtualWarehouse = new MesWmWarehouseDO(); + virtualWarehouse.setId(WAREHOUSE_ID); + virtualWarehouse.setCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + + virtualLocation = new MesWmWarehouseLocationDO(); + virtualLocation.setId(LOCATION_ID); + virtualLocation.setCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); + + virtualArea = new MesWmWarehouseAreaDO(); + virtualArea.setId(AREA_ID); + virtualArea.setCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); + + when(warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE)) + .thenReturn(virtualWarehouse); + when(locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION)) + .thenReturn(virtualLocation); + when(areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA)) + .thenReturn(virtualArea); + + lenient().when(routeService.validateRouteExists(anyLong())).thenAnswer(invocation -> { + Long routeId = invocation.getArgument(0); + return new MesProRouteDO().setId(routeId); + }); + + // mock createItemConsumeLineBatch:模拟 insertBatch 后填充 ID + AtomicLong lineIdSeq = new AtomicLong(1000L); + doAnswer(invocation -> { + List lines = invocation.getArgument(0); + for (MesWmItemConsumeLineDO line : lines) { + line.setId(lineIdSeq.getAndIncrement()); + } + return null; + }).when(itemConsumeLineService).createItemConsumeLineBatch(any()); + } + + private MesProFeedbackDO buildFeedback() { + return MesProFeedbackDO.builder() + .id(randomLongId()).workOrderId(randomLongId()).taskId(randomLongId()) + .workstationId(randomLongId()).processId(randomLongId()).routeId(randomLongId()) + .itemId(randomLongId()).feedbackQuantity(BigDecimal.TEN) + .build(); + } + + // ========== generateItemConsume ========== + + @Test + public void testGenerateItemConsume_routeContextIncomplete() { + MesProFeedbackDO feedback = buildFeedback(); + feedback.setRouteId(null); + assertServiceException(() -> itemConsumeService.generateItemConsume(feedback), PRO_FEEDBACK_ROUTE_PROCESS_INVALID); + verify(routeProductBomService, never()).getRouteProductBomList(any(), any(), any()); + } + + @Test + public void testGenerateItemConsume_routeNotExists() { + MesProFeedbackDO feedback = buildFeedback(); + doThrow(ServiceExceptionUtil.exception(PRO_ROUTE_NOT_EXISTS)).when(routeService) + .validateRouteExists(feedback.getRouteId()); + assertServiceException(() -> itemConsumeService.generateItemConsume(feedback), PRO_ROUTE_NOT_EXISTS); + verify(routeProductBomService, never()).getRouteProductBomList(any(), any(), any()); + } + + @Test + public void testGenerateItemConsume_noBom() { + // 准备 + MesProFeedbackDO feedback = buildFeedback(); + when(routeProductBomService.getRouteProductBomList( + feedback.getRouteId(), feedback.getProcessId(), feedback.getItemId())) + .thenReturn(Collections.emptyList()); + + // 调用 + MesWmItemConsumeDO result = itemConsumeService.generateItemConsume(feedback); + + // 断言 + assertNull(result); + verify(itemConsumeLineService, never()).createItemConsumeLineBatch(any()); + verify(itemConsumeDetailService, never()).createItemConsumeDetailBatch(any()); + } + + @Test + public void testGenerateItemConsume_noStock() { + // 准备:1 个 BOM 物料,线边库无库存 + MesProFeedbackDO feedback = buildFeedback(); + Long bomItemId = randomLongId(); + MesProRouteProductBomDO bom = new MesProRouteProductBomDO(); + bom.setItemId(bomItemId); + bom.setQuantity(new BigDecimal("2")); // 用料比例 = 2 + when(routeProductBomService.getRouteProductBomList(any(), any(), any())) + .thenReturn(List.of(bom)); + when(materialStockService.getMaterialStockList(any(MesWmMaterialStockListReqVO.class))) + .thenReturn(Collections.emptyList()); + + // 调用 + MesWmItemConsumeDO result = itemConsumeService.generateItemConsume(feedback); + + // 断言 1:消耗单头已入库 + assertNotNull(result); + assertNotNull(result.getId()); + assertEquals(MesWmItemConsumeStatusEnum.PREPARE.getStatus(), result.getStatus()); + assertEquals(feedback.getId(), result.getFeedbackId()); + + // 断言 2:消耗行正确 + @SuppressWarnings("unchecked") + ArgumentCaptor> lineCaptor = ArgumentCaptor.forClass(List.class); + verify(itemConsumeLineService).createItemConsumeLineBatch(lineCaptor.capture()); + List lines = lineCaptor.getValue(); + assertEquals(1, lines.size()); + assertEquals(bomItemId, lines.get(0).getItemId()); + // 消耗数量 = 2 × 10 = 20 + assertEquals(0, new BigDecimal("20").compareTo(lines.get(0).getQuantity())); + + // 断言 3:生成 1 条无批次的 detail + @SuppressWarnings("unchecked") + ArgumentCaptor> detailCaptor = ArgumentCaptor.forClass(List.class); + verify(itemConsumeDetailService).createItemConsumeDetailBatch(detailCaptor.capture()); + List details = detailCaptor.getValue(); + assertEquals(1, details.size()); + MesWmItemConsumeDetailDO detail = details.get(0); + assertEquals(bomItemId, detail.getItemId()); + assertEquals(0, new BigDecimal("20").compareTo(detail.getQuantity())); + assertNull(detail.getMaterialStockId()); + assertNull(detail.getBatchId()); + assertEquals(WAREHOUSE_ID, detail.getWarehouseId()); + assertEquals(LOCATION_ID, detail.getLocationId()); + assertEquals(AREA_ID, detail.getAreaId()); + } + + @Test + public void testGenerateItemConsume_singleBatchSufficient() { + // 准备:1 个 BOM 物料,线边库有 1 个批次且库存充足 + MesProFeedbackDO feedback = buildFeedback(); + Long bomItemId = randomLongId(); + MesProRouteProductBomDO bom = new MesProRouteProductBomDO(); + bom.setItemId(bomItemId); + bom.setQuantity(new BigDecimal("3")); // 消耗 = 3 × 10 = 30 + when(routeProductBomService.getRouteProductBomList(any(), any(), any())) + .thenReturn(List.of(bom)); + + Long stockId = randomLongId(); + Long batchId = randomLongId(); + MesWmMaterialStockDO stock = new MesWmMaterialStockDO(); + stock.setId(stockId); + stock.setItemId(bomItemId); + stock.setQuantity(new BigDecimal("50")); // 库存 50 > 需求 30 + stock.setBatchId(batchId); + stock.setBatchCode("BATCH-001"); + when(materialStockService.getMaterialStockList(any(MesWmMaterialStockListReqVO.class))) + .thenReturn(List.of(stock)); + + // 调用 + MesWmItemConsumeDO result = itemConsumeService.generateItemConsume(feedback); + + // 断言:生成 1 条带批次的 detail + assertNotNull(result); + @SuppressWarnings("unchecked") + ArgumentCaptor> detailCaptor = ArgumentCaptor.forClass(List.class); + verify(itemConsumeDetailService).createItemConsumeDetailBatch(detailCaptor.capture()); + List details = detailCaptor.getValue(); + assertEquals(1, details.size()); + MesWmItemConsumeDetailDO detail = details.get(0); + assertEquals(0, new BigDecimal("30").compareTo(detail.getQuantity())); + assertEquals(stockId, detail.getMaterialStockId()); + assertEquals(batchId, detail.getBatchId()); + assertEquals("BATCH-001", detail.getBatchCode()); + } + + @Test + public void testGenerateItemConsume_multiBatchFifo() { + // 准备:1 个 BOM 物料,需消耗 30,线边库有 2 个批次(20 + 15) + MesProFeedbackDO feedback = buildFeedback(); + Long bomItemId = randomLongId(); + MesProRouteProductBomDO bom = new MesProRouteProductBomDO(); + bom.setItemId(bomItemId); + bom.setQuantity(new BigDecimal("3")); // 消耗 = 3 × 10 = 30 + when(routeProductBomService.getRouteProductBomList(any(), any(), any())) + .thenReturn(List.of(bom)); + + Long stockId1 = randomLongId(); + Long stockId2 = randomLongId(); + MesWmMaterialStockDO stock1 = new MesWmMaterialStockDO(); + stock1.setId(stockId1); + stock1.setItemId(bomItemId); + stock1.setQuantity(new BigDecimal("20")); // 先进先出:先消耗这批 + stock1.setBatchId(1L); + stock1.setBatchCode("BATCH-001"); + + MesWmMaterialStockDO stock2 = new MesWmMaterialStockDO(); + stock2.setId(stockId2); + stock2.setItemId(bomItemId); + stock2.setQuantity(new BigDecimal("15")); + stock2.setBatchId(2L); + stock2.setBatchCode("BATCH-002"); + + // FIFO 顺序返回 + when(materialStockService.getMaterialStockList(any(MesWmMaterialStockListReqVO.class))) + .thenReturn(Arrays.asList(stock1, stock2)); + + // 调用 + MesWmItemConsumeDO result = itemConsumeService.generateItemConsume(feedback); + + // 断言:生成 2 条带批次的 detail(20 + 10) + assertNotNull(result); + @SuppressWarnings("unchecked") + ArgumentCaptor> detailCaptor = ArgumentCaptor.forClass(List.class); + verify(itemConsumeDetailService).createItemConsumeDetailBatch(detailCaptor.capture()); + List details = detailCaptor.getValue(); + assertEquals(2, details.size()); + + // 第 1 条:批次 1 全部消耗 20 + assertEquals(stockId1, details.get(0).getMaterialStockId()); + assertEquals(0, new BigDecimal("20").compareTo(details.get(0).getQuantity())); + assertEquals("BATCH-001", details.get(0).getBatchCode()); + + // 第 2 条:批次 2 消耗 10(30 - 20 = 10) + assertEquals(stockId2, details.get(1).getMaterialStockId()); + assertEquals(0, new BigDecimal("10").compareTo(details.get(1).getQuantity())); + assertEquals("BATCH-002", details.get(1).getBatchCode()); + } + + @Test + public void testGenerateItemConsume_insufficientStock() { + // 准备:需消耗 30,线边库只有 1 个批次(库存 18),不足部分生成无批次 detail + MesProFeedbackDO feedback = buildFeedback(); + Long bomItemId = randomLongId(); + MesProRouteProductBomDO bom = new MesProRouteProductBomDO(); + bom.setItemId(bomItemId); + bom.setQuantity(new BigDecimal("3")); // 消耗 = 3 × 10 = 30 + when(routeProductBomService.getRouteProductBomList(any(), any(), any())) + .thenReturn(List.of(bom)); + + Long stockId = randomLongId(); + MesWmMaterialStockDO stock = new MesWmMaterialStockDO(); + stock.setId(stockId); + stock.setItemId(bomItemId); + stock.setQuantity(new BigDecimal("18")); // 不够 30 + stock.setBatchId(1L); + stock.setBatchCode("BATCH-001"); + when(materialStockService.getMaterialStockList(any(MesWmMaterialStockListReqVO.class))) + .thenReturn(List.of(stock)); + + // 调用 + MesWmItemConsumeDO result = itemConsumeService.generateItemConsume(feedback); + + // 断言:2 条 detail(18 带批次 + 12 无批次) + assertNotNull(result); + @SuppressWarnings("unchecked") + ArgumentCaptor> detailCaptor = ArgumentCaptor.forClass(List.class); + verify(itemConsumeDetailService).createItemConsumeDetailBatch(detailCaptor.capture()); + List details = detailCaptor.getValue(); + assertEquals(2, details.size()); + + // 第 1 条:批次全部消耗 18 + assertEquals(stockId, details.get(0).getMaterialStockId()); + assertEquals(0, new BigDecimal("18").compareTo(details.get(0).getQuantity())); + assertEquals("BATCH-001", details.get(0).getBatchCode()); + + // 第 2 条:剩余 12 无批次 + assertNull(details.get(1).getMaterialStockId()); + assertEquals(0, new BigDecimal("12").compareTo(details.get(1).getQuantity())); + assertNull(details.get(1).getBatchId()); + } + + @Test + public void testGenerateItemConsume_multipleBomItems() { + // 准备:2 个 BOM 物料 + MesProFeedbackDO feedback = buildFeedback(); + Long itemA = randomLongId(); + Long itemB = randomLongId(); + + MesProRouteProductBomDO bomA = new MesProRouteProductBomDO(); + bomA.setItemId(itemA); + bomA.setQuantity(new BigDecimal("1")); // 消耗 = 1 × 10 = 10 + + MesProRouteProductBomDO bomB = new MesProRouteProductBomDO(); + bomB.setItemId(itemB); + bomB.setQuantity(new BigDecimal("2")); // 消耗 = 2 × 10 = 20 + + when(routeProductBomService.getRouteProductBomList(any(), any(), any())) + .thenReturn(Arrays.asList(bomA, bomB)); + + // 物料 A 有库存,物料 B 无库存 + MesWmMaterialStockDO stockA = new MesWmMaterialStockDO(); + stockA.setId(randomLongId()); + stockA.setItemId(itemA); + stockA.setQuantity(new BigDecimal("100")); + stockA.setBatchId(1L); + stockA.setBatchCode("BATCH-A"); + + when(materialStockService.getMaterialStockList(argThat((MesWmMaterialStockListReqVO req) -> + req != null && itemA.equals(req.getItemId())))) + .thenReturn(List.of(stockA)); + when(materialStockService.getMaterialStockList(argThat((MesWmMaterialStockListReqVO req) -> + req != null && itemB.equals(req.getItemId())))) + .thenReturn(Collections.emptyList()); + + // 调用 + MesWmItemConsumeDO result = itemConsumeService.generateItemConsume(feedback); + + // 断言:2 条消耗行,2 条 detail + assertNotNull(result); + + @SuppressWarnings("unchecked") + ArgumentCaptor> lineCaptor = ArgumentCaptor.forClass(List.class); + verify(itemConsumeLineService).createItemConsumeLineBatch(lineCaptor.capture()); + assertEquals(2, lineCaptor.getValue().size()); + + @SuppressWarnings("unchecked") + ArgumentCaptor> detailCaptor = ArgumentCaptor.forClass(List.class); + verify(itemConsumeDetailService).createItemConsumeDetailBatch(detailCaptor.capture()); + List details = detailCaptor.getValue(); + assertEquals(2, details.size()); + + // 物料 A:有批次 + MesWmItemConsumeDetailDO detailA = details.stream() + .filter(d -> itemA.equals(d.getItemId())).findFirst().orElseThrow(); + assertEquals(0, new BigDecimal("10").compareTo(detailA.getQuantity())); + assertNotNull(detailA.getMaterialStockId()); + assertEquals("BATCH-A", detailA.getBatchCode()); + + // 物料 B:无批次 + MesWmItemConsumeDetailDO detailB = details.stream() + .filter(d -> itemB.equals(d.getItemId())).findFirst().orElseThrow(); + assertEquals(0, new BigDecimal("20").compareTo(detailB.getQuantity())); + assertNull(detailB.getMaterialStockId()); + } + + // ========== finishItemConsume ========== + + @Test + public void testFinishItemConsume_withDetails() { + // 准备:插入一条消耗记录 + MesWmItemConsumeDO consume = MesWmItemConsumeDO.builder() + .workOrderId(randomLongId()).taskId(randomLongId()) + .workstationId(randomLongId()).processId(randomLongId()) + .feedbackId(randomLongId()).consumeDate(java.time.LocalDateTime.now()) + .status(MesWmItemConsumeStatusEnum.PREPARE.getStatus()).build(); + itemConsumeMapper.insert(consume); + + // mock detail 列表 + Long lineId1 = randomLongId(); + Long lineId2 = randomLongId(); + MesWmItemConsumeDetailDO detail1 = MesWmItemConsumeDetailDO.builder() + .consumeId(consume.getId()).lineId(lineId1).itemId(randomLongId()) + .quantity(new BigDecimal("20")).batchId(1L).batchCode("BATCH-001") + .warehouseId(WAREHOUSE_ID).locationId(LOCATION_ID).areaId(AREA_ID).build(); + MesWmItemConsumeDetailDO detail2 = MesWmItemConsumeDetailDO.builder() + .consumeId(consume.getId()).lineId(lineId2).itemId(randomLongId()) + .quantity(new BigDecimal("12")) + .warehouseId(WAREHOUSE_ID).locationId(LOCATION_ID).areaId(AREA_ID).build(); + when(itemConsumeDetailService.getItemConsumeDetailListByConsumeId(consume.getId())) + .thenReturn(Arrays.asList(detail1, detail2)); + + // 调用 + itemConsumeService.finishItemConsume(consume.getId()); + + // 断言 1:状态更新为已完成 + MesWmItemConsumeDO updated = itemConsumeMapper.selectById(consume.getId()); + assertEquals(MesWmItemConsumeStatusEnum.FINISHED.getStatus(), updated.getStatus()); + + // 断言 2:创建了 2 次库存事务 + ArgumentCaptor txCaptor = ArgumentCaptor.forClass(MesWmTransactionSaveReqDTO.class); + verify(wmTransactionService, times(2)).createTransaction(txCaptor.capture()); + List txList = txCaptor.getAllValues(); + + // 验证第 1 条事务 + MesWmTransactionSaveReqDTO tx1 = txList.get(0); + assertEquals(MesWmTransactionTypeEnum.OUT.getType(), tx1.getType()); + assertEquals(detail1.getItemId(), tx1.getItemId()); + assertEquals(0, new BigDecimal("-20").compareTo(tx1.getQuantity())); + assertEquals(1L, tx1.getBatchId()); + assertEquals("BATCH-001", tx1.getBatchCode()); + assertEquals(WAREHOUSE_ID, tx1.getWarehouseId()); + assertFalse(tx1.getCheckFlag()); + assertEquals(MesBizTypeConstants.WM_ITEM_CONSUME, tx1.getBizType()); + assertEquals(consume.getId(), tx1.getBizId()); + assertEquals(lineId1, tx1.getBizLineId()); + + // 验证第 2 条事务(无批次) + MesWmTransactionSaveReqDTO tx2 = txList.get(1); + assertEquals(detail2.getItemId(), tx2.getItemId()); + assertEquals(0, new BigDecimal("-12").compareTo(tx2.getQuantity())); + assertNull(tx2.getBatchId()); + } + + @Test + public void testFinishItemConsume_emptyDetails() { + // 准备:插入一条消耗记录,但没有 detail + MesWmItemConsumeDO consume = MesWmItemConsumeDO.builder() + .workOrderId(randomLongId()).taskId(randomLongId()) + .workstationId(randomLongId()).processId(randomLongId()) + .feedbackId(randomLongId()).consumeDate(java.time.LocalDateTime.now()) + .status(MesWmItemConsumeStatusEnum.PREPARE.getStatus()).build(); + itemConsumeMapper.insert(consume); + + when(itemConsumeDetailService.getItemConsumeDetailListByConsumeId(consume.getId())) + .thenReturn(Collections.emptyList()); + + // 调用 + itemConsumeService.finishItemConsume(consume.getId()); + + // 断言:状态更新为已完成,但无事务创建 + MesWmItemConsumeDO updated = itemConsumeMapper.selectById(consume.getId()); + assertEquals(MesWmItemConsumeStatusEnum.FINISHED.getStatus(), updated.getStatus()); + verify(wmTransactionService, never()).createTransaction(any()); + } + + // ========== getByFeedbackId ========== + + @Test + public void testGetByFeedbackId_exists() { + Long feedbackId = randomLongId(); + MesWmItemConsumeDO consume = MesWmItemConsumeDO.builder() + .workOrderId(randomLongId()).taskId(randomLongId()) + .workstationId(randomLongId()).processId(randomLongId()) + .feedbackId(feedbackId).consumeDate(java.time.LocalDateTime.now()) + .status(MesWmItemConsumeStatusEnum.PREPARE.getStatus()).build(); + itemConsumeMapper.insert(consume); + + MesWmItemConsumeDO result = itemConsumeService.getByFeedbackId(feedbackId); + assertNotNull(result); + assertEquals(consume.getId(), result.getId()); + } + + @Test + public void testGetByFeedbackId_notExists() { + MesWmItemConsumeDO result = itemConsumeService.getByFeedbackId(randomLongId()); + assertNull(result); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImplTest.java new file mode 100644 index 000000000..fe59cc851 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImplTest.java @@ -0,0 +1,160 @@ +package cn.iocoder.yudao.module.mes.service.wm.itemreceipt; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import jakarta.annotation.Resource; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Collections; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +/** + * {@link MesWmItemReceiptServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesWmItemReceiptServiceImpl.class) +public class MesWmItemReceiptServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmItemReceiptServiceImpl itemReceiptService; + + @Resource + private MesWmItemReceiptMapper itemReceiptMapper; + + @MockitoBean + private MesWmItemReceiptLineService itemReceiptLineService; + @MockitoBean + private MesWmItemReceiptDetailService itemReceiptDetailService; + @MockitoBean + private MesWmArrivalNoticeService arrivalNoticeService; + @MockitoBean + private MesMdVendorService vendorService; + @MockitoBean + private MesQcIqcService iqcService; + @MockitoBean + private MesWmTransactionService wmTransactionService; + + // ========== finishItemReceipt ========== + + @Test + public void testFinishItemReceipt_success_withNoticeId() { + // mock 数据:插入一条待入库状态的入库单(有关联到货通知单) + Long noticeId = randomLongId(); + MesWmItemReceiptDO receipt = randomPojo(MesWmItemReceiptDO.class, o -> { + o.setStatus(MesWmItemReceiptStatusEnum.APPROVED.getStatus()); + o.setNoticeId(noticeId); + }); + itemReceiptMapper.insert(receipt); + Long receiptId = receipt.getId(); + + // mock 明细列表 + MesWmItemReceiptDetailDO detail1 = randomPojo(MesWmItemReceiptDetailDO.class, o -> { + o.setReceiptId(receiptId); + o.setQuantity(BigDecimal.valueOf(100)); + }); + MesWmItemReceiptDetailDO detail2 = randomPojo(MesWmItemReceiptDetailDO.class, o -> { + o.setReceiptId(receiptId); + o.setQuantity(BigDecimal.valueOf(50)); + }); + when(itemReceiptDetailService.getItemReceiptDetailListByReceiptId(eq(receiptId))) + .thenReturn(Arrays.asList(detail1, detail2)); + + // 调用 + itemReceiptService.finishItemReceipt(receiptId); + + // 断言 1:状态更新为已完成 + MesWmItemReceiptDO updated = itemReceiptMapper.selectById(receiptId); + assertEquals(MesWmItemReceiptStatusEnum.FINISHED.getStatus(), updated.getStatus()); + // 断言 2:库存事务被创建(2 条明细) + verify(wmTransactionService).createTransactionList(anyList()); + // 断言 3:到货通知单被完成 + verify(arrivalNoticeService).finishArrivalNotice(eq(noticeId)); + } + + @Test + public void testFinishItemReceipt_success_withoutNoticeId() { + // mock 数据:插入一条待入库状态的入库单(无关联到货通知单) + MesWmItemReceiptDO receipt = randomPojo(MesWmItemReceiptDO.class, o -> { + o.setStatus(MesWmItemReceiptStatusEnum.APPROVED.getStatus()); + o.setNoticeId(null); // 无到货通知单 + }); + itemReceiptMapper.insert(receipt); + Long receiptId = receipt.getId(); + + // mock 空明细 + when(itemReceiptDetailService.getItemReceiptDetailListByReceiptId(eq(receiptId))) + .thenReturn(Collections.emptyList()); + + // 调用 + itemReceiptService.finishItemReceipt(receiptId); + + // 断言 1:状态更新为已完成 + MesWmItemReceiptDO updated = itemReceiptMapper.selectById(receiptId); + assertEquals(MesWmItemReceiptStatusEnum.FINISHED.getStatus(), updated.getStatus()); + // 断言 2:库存事务仍被调用(空列表) + verify(wmTransactionService).createTransactionList(anyList()); + // 断言 3:到货通知单完成方法不被调用 + verify(arrivalNoticeService, never()).finishArrivalNotice(any()); + } + + @Test + public void testFinishItemReceipt_notExists() { + // 准备参数 + Long receiptId = randomLongId(); + + // 调用,并断言异常 + assertServiceException( + () -> itemReceiptService.finishItemReceipt(receiptId), + WM_ITEM_RECEIPT_NOT_EXISTS); + } + + @Test + public void testFinishItemReceipt_statusNotApproved() { + // mock 数据:插入一条草稿状态 + MesWmItemReceiptDO receipt = randomPojo(MesWmItemReceiptDO.class, o -> { + o.setStatus(MesWmItemReceiptStatusEnum.PREPARE.getStatus()); + }); + itemReceiptMapper.insert(receipt); + + // 调用,并断言异常 + assertServiceException( + () -> itemReceiptService.finishItemReceipt(receipt.getId()), + WM_ITEM_RECEIPT_STATUS_ERROR); + } + + @Test + public void testFinishItemReceipt_statusAlreadyFinished() { + // mock 数据:插入一条已完成状态 + MesWmItemReceiptDO receipt = randomPojo(MesWmItemReceiptDO.class, o -> { + o.setStatus(MesWmItemReceiptStatusEnum.FINISHED.getStatus()); + }); + itemReceiptMapper.insert(receipt); + + // 调用,并断言异常 + assertServiceException( + () -> itemReceiptService.finishItemReceipt(receipt.getId()), + WM_ITEM_RECEIPT_STATUS_ERROR); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImplTest.java new file mode 100644 index 000000000..74392a994 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImplTest.java @@ -0,0 +1,195 @@ +package cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutsourceReceiptLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt.MesWmOutsourceReceiptMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmOutsourceReceiptStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import jakarta.annotation.Resource; + +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesWmOutsourceReceiptServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesWmOutsourceReceiptServiceImpl.class) +public class MesWmOutsourceReceiptServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmOutsourceReceiptServiceImpl outsourceReceiptService; + + @Resource + private MesWmOutsourceReceiptMapper outsourceReceiptMapper; + + @MockitoBean + private MesWmOutsourceReceiptLineService outsourceReceiptLineService; + @MockitoBean + private MesWmOutsourceReceiptDetailService outsourceReceiptDetailService; + @MockitoBean + private MesWmTransactionService wmTransactionService; + @MockitoBean + private MesMdVendorService vendorService; + @MockitoBean + private MesMdItemService itemService; + @MockitoBean + private MesProWorkOrderService workOrderService; + + @Test + public void testUpdateOutsourceReceiptWhenIqcFinish_success_bothQualifiedAndUnqualified() { + // mock 数据:插入一条待检验状态的外协入库单 + MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> { + o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus()); + }); + outsourceReceiptMapper.insert(receipt); + // 准备参数 + Long receiptId = receipt.getId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(80); + BigDecimal unqualifiedQuantity = BigDecimal.valueOf(20); + + // mock 行查询 + MesWmOutsourceReceiptLineDO line = randomPojo(MesWmOutsourceReceiptLineDO.class, o -> { + o.setId(lineId); + o.setReceiptId(receiptId); + o.setQuantity(BigDecimal.valueOf(100)); + }); + when(outsourceReceiptLineService.getOutsourceReceiptLine(eq(lineId))).thenReturn(line); + + // 调用 + outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish( + receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity); + + // 断言:合格品行更新 + verify(outsourceReceiptLineService).updateOutsourceReceiptLineDO(argThat(updateLine -> + lineId.equals(updateLine.getId()) + && MesWmQualityStatusEnum.PASS.getStatus().equals(updateLine.getQualityStatus()) + && iqcId.equals(updateLine.getIqcId()) + && qualifiedQuantity.equals(updateLine.getQuantity()))); + // 断言:不合格品新增行 + verify(outsourceReceiptLineService).createOutsourceReceiptLineDO(argThat(newLine -> + newLine.getId() == null + && MesWmQualityStatusEnum.FAIL.getStatus().equals(newLine.getQualityStatus()) + && iqcId.equals(newLine.getIqcId()) + && unqualifiedQuantity.equals(newLine.getQuantity()))); + // 断言:主表状态更新为待上架 + MesWmOutsourceReceiptDO updatedReceipt = outsourceReceiptMapper.selectById(receiptId); + assertEquals(MesWmOutsourceReceiptStatusEnum.APPROVING.getStatus(), updatedReceipt.getStatus()); + } + + @Test + public void testUpdateOutsourceReceiptWhenIqcFinish_success_onlyQualified() { + // mock 数据:插入一条待检验状态的外协入库单 + MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> { + o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus()); + }); + outsourceReceiptMapper.insert(receipt); + // 准备参数 + Long receiptId = receipt.getId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(100); + BigDecimal unqualifiedQuantity = BigDecimal.ZERO; // 没有不合格品 + + // mock 行查询 + MesWmOutsourceReceiptLineDO line = randomPojo(MesWmOutsourceReceiptLineDO.class, o -> { + o.setId(lineId); + o.setReceiptId(receiptId); + }); + when(outsourceReceiptLineService.getOutsourceReceiptLine(eq(lineId))).thenReturn(line); + + // 调用 + outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish( + receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity); + + // 断言:合格品行更新 + verify(outsourceReceiptLineService).updateOutsourceReceiptLineDO(argThat(updateLine -> + lineId.equals(updateLine.getId()))); + // 断言:不合格品不应该新增行(数量为 0) + verify(outsourceReceiptLineService, never()).createOutsourceReceiptLineDO(any()); + // 断言:主表状态更新为待上架 + MesWmOutsourceReceiptDO updatedReceipt = outsourceReceiptMapper.selectById(receiptId); + assertEquals(MesWmOutsourceReceiptStatusEnum.APPROVING.getStatus(), updatedReceipt.getStatus()); + } + + @Test + public void testUpdateOutsourceReceiptWhenIqcFinish_receiptNotExists() { + // 准备参数 + Long receiptId = randomLongId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(100); + BigDecimal unqualifiedQuantity = BigDecimal.ZERO; + + // 调用,并断言异常 + assertServiceException( + () -> outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish( + receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity), + WM_OUTSOURCE_RECEIPT_NOT_EXISTS); + } + + @Test + public void testUpdateOutsourceReceiptWhenIqcFinish_statusNotConfirmed() { + // mock 数据:插入一条草稿状态的外协入库单(非待检验状态) + MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> { + o.setStatus(MesWmOutsourceReceiptStatusEnum.PREPARE.getStatus()); + }); + outsourceReceiptMapper.insert(receipt); + // 准备参数 + Long receiptId = receipt.getId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(100); + BigDecimal unqualifiedQuantity = BigDecimal.ZERO; + + // 调用,并断言异常 + assertServiceException( + () -> outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish( + receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity), + WM_OUTSOURCE_RECEIPT_STATUS_ERROR); + } + + @Test + public void testUpdateOutsourceReceiptWhenIqcFinish_lineNotExists() { + // mock 数据:插入一条待检验状态的外协入库单 + MesWmOutsourceReceiptDO receipt = randomPojo(MesWmOutsourceReceiptDO.class, o -> { + o.setStatus(MesWmOutsourceReceiptStatusEnum.CONFIRMED.getStatus()); + }); + outsourceReceiptMapper.insert(receipt); + // 准备参数 + Long receiptId = receipt.getId(); + Long lineId = randomLongId(); + Long iqcId = randomLongId(); + BigDecimal qualifiedQuantity = BigDecimal.valueOf(100); + BigDecimal unqualifiedQuantity = BigDecimal.ZERO; + + // mock 行查询返回 null + when(outsourceReceiptLineService.getOutsourceReceiptLine(eq(lineId))).thenReturn(null); + + // 调用,并断言异常 + assertServiceException( + () -> outsourceReceiptService.updateOutsourceReceiptWhenIqcFinish( + receiptId, lineId, iqcId, qualifiedQuantity, unqualifiedQuantity), + WM_OUTSOURCE_RECEIPT_LINE_NOT_EXISTS); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImplTest.java new file mode 100644 index 000000000..3ea0824e2 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImplTest.java @@ -0,0 +1,255 @@ +package cn.iocoder.yudao.module.mes.service.wm.productproduce; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; +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.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productproduce.MesWmProductProduceMapper; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductProduceStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; +import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.math.BigDecimal; +import java.util.List; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesWmProductProduceServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesWmProductProduceServiceImpl.class) +public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmProductProduceServiceImpl productProduceService; + + @Resource + private MesWmProductProduceMapper productProduceMapper; + + @MockitoBean + private MesWmProductProduceLineService productProduceLineService; + @MockitoBean + private MesWmProductProduceDetailService productProduceDetailService; + @MockitoBean + private MesProWorkOrderService workOrderService; + @MockitoBean + private MesWmBatchService batchService; + @MockitoBean + private MesWmTransactionService wmTransactionService; + @MockitoBean + private MesWmWarehouseService warehouseService; + @MockitoBean + private MesWmWarehouseLocationService locationService; + @MockitoBean + private MesWmWarehouseAreaService areaService; + + @Test + public void testSplitPendingAndFinishProduce_withUnqualified() { + // 准备数据:插入一个 PREPARE 状态的产出单 + Long feedbackId = randomLongId(); + Long itemId = randomLongId(); + Long batchId = randomLongId(); + String batchCode = "BATCH-001"; + + MesWmProductProduceDO produce = randomPojo(MesWmProductProduceDO.class, o -> { + o.setFeedbackId(feedbackId); + o.setStatus(MesWmProductProduceStatusEnum.PREPARE.getStatus()); + }); + productProduceMapper.insert(produce); + + // mock: 虚拟线边库 + Long whId = randomLongId(), locId = randomLongId(), areaId = randomLongId(); + MesWmWarehouseDO wh = new MesWmWarehouseDO(); wh.setId(whId); + MesWmWarehouseLocationDO loc = new MesWmWarehouseLocationDO(); loc.setId(locId); + MesWmWarehouseAreaDO area = new MesWmWarehouseAreaDO(); area.setId(areaId); + when(warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE)).thenReturn(wh); + when(locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION)).thenReturn(loc); + when(areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA)).thenReturn(area); + + // mock: 返回一条 PENDING 的产出行 + MesWmProductProduceLineDO pendingLine = MesWmProductProduceLineDO.builder() + .id(100L).produceId(produce.getId()).feedbackId(feedbackId) + .itemId(itemId).quantity(BigDecimal.valueOf(100)) + .batchId(batchId).batchCode(batchCode) + .qualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()) + .build(); + when(productProduceLineService.getProductProduceLineListByProduceId(produce.getId())) + .thenReturn(List.of(pendingLine)); + + // mock: finishProductProduce 内部会再查一次行和明细(用于创建库存事务) + // 由于 finishProductProduce 在拆分行后调用,此时行已经变了,但由于 line/detail 是 mock 的, + // 我们需要 mock 已拆分后的行给 finishProductProduce + MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() + .id(100L).produceId(produce.getId()).itemId(itemId) + .quantity(BigDecimal.valueOf(80)) + .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) + .build(); + MesWmProductProduceLineDO unqualifiedLine = MesWmProductProduceLineDO.builder() + .id(101L).produceId(produce.getId()).itemId(itemId) + .quantity(BigDecimal.valueOf(20)) + .qualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) + .build(); + // finishProductProduce 内部第二次调用 getProductProduceLineListByProduceId + when(productProduceLineService.getProductProduceLineListByProduceId(produce.getId())) + .thenReturn(List.of(pendingLine)) // 第 1 次:splitPendingAndFinishProduce 查待检行 + .thenReturn(List.of(qualifiedLine, unqualifiedLine)); // 第 2 次:finishProductProduce 查所有行 + + // mock: finishProductProduce 中按行查明细 + MesWmProductProduceDetailDO qualifiedDetail = MesWmProductProduceDetailDO.builder() + .lineId(100L).quantity(BigDecimal.valueOf(80)).build(); + MesWmProductProduceDetailDO unqualifiedDetail = MesWmProductProduceDetailDO.builder() + .lineId(101L).quantity(BigDecimal.valueOf(20)).build(); + when(productProduceDetailService.getProductProduceDetailListByLineId(100L)) + .thenReturn(List.of(qualifiedDetail)); + when(productProduceDetailService.getProductProduceDetailListByLineId(101L)) + .thenReturn(List.of(unqualifiedDetail)); + + // 调用 + productProduceService.splitPendingAndFinishProduce(feedbackId, BigDecimal.valueOf(80), BigDecimal.valueOf(20)); + + // 断言 1:不合格品行 - 新建了一行 + ArgumentCaptor lineCaptor = ArgumentCaptor.forClass(MesWmProductProduceLineDO.class); + verify(productProduceLineService).createProductProduceLine(lineCaptor.capture()); + MesWmProductProduceLineDO createdLine = lineCaptor.getValue(); + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), createdLine.getQualityStatus()); + assertEquals(0, BigDecimal.valueOf(20).compareTo(createdLine.getQuantity())); + assertEquals(itemId, createdLine.getItemId()); + + // 断言 2:原待检行 - 更新为合格品 + ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(MesWmProductProduceLineDO.class); + verify(productProduceLineService).updateProductProduceLine(updateCaptor.capture()); + MesWmProductProduceLineDO updatedLine = updateCaptor.getValue(); + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), updatedLine.getQualityStatus()); + assertEquals(0, BigDecimal.valueOf(80).compareTo(updatedLine.getQuantity())); + + // 断言 3:生成了 2 条明细(不合格品明细 + 合格品明细) + verify(productProduceDetailService, times(2)).createProductProduceDetail(any()); + + // 断言 4:产出单状态更新为已完成 + MesWmProductProduceDO updatedProduce = productProduceMapper.selectById(produce.getId()); + assertEquals(MesWmProductProduceStatusEnum.FINISHED.getStatus(), updatedProduce.getStatus()); + + // 断言 5:创建了库存事务 + verify(wmTransactionService, times(2)).createTransaction(any()); + } + + @Test + public void testSplitPendingAndFinishProduce_allQualified() { + // 准备数据:全部合格品场景 + Long feedbackId = randomLongId(); + Long itemId = randomLongId(); + + MesWmProductProduceDO produce = randomPojo(MesWmProductProduceDO.class, o -> { + o.setFeedbackId(feedbackId); + o.setStatus(MesWmProductProduceStatusEnum.PREPARE.getStatus()); + }); + productProduceMapper.insert(produce); + + // mock: 虚拟线边库 + Long whId = randomLongId(), locId = randomLongId(), areaId = randomLongId(); + MesWmWarehouseDO wh = new MesWmWarehouseDO(); wh.setId(whId); + MesWmWarehouseLocationDO loc = new MesWmWarehouseLocationDO(); loc.setId(locId); + MesWmWarehouseAreaDO area = new MesWmWarehouseAreaDO(); area.setId(areaId); + when(warehouseService.getWarehouseByCode(any())).thenReturn(wh); + when(locationService.getWarehouseLocationByCode(any())).thenReturn(loc); + when(areaService.getWarehouseAreaByCode(any())).thenReturn(area); + + MesWmProductProduceLineDO pendingLine = MesWmProductProduceLineDO.builder() + .id(200L).produceId(produce.getId()).feedbackId(feedbackId) + .itemId(itemId).quantity(BigDecimal.valueOf(50)) + .qualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()) + .build(); + + // 第 1 次查行(拆分阶段)返回 PENDING 行;第 2 次查行(finishProductProduce)返回已更新的合格行 + MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() + .id(200L).produceId(produce.getId()).itemId(itemId) + .quantity(BigDecimal.valueOf(50)) + .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) + .build(); + when(productProduceLineService.getProductProduceLineListByProduceId(produce.getId())) + .thenReturn(List.of(pendingLine)) + .thenReturn(List.of(qualifiedLine)); + + // mock: finishProductProduce 中按行查明细 + MesWmProductProduceDetailDO detail = MesWmProductProduceDetailDO.builder() + .lineId(200L).quantity(BigDecimal.valueOf(50)).build(); + when(productProduceDetailService.getProductProduceDetailListByLineId(200L)) + .thenReturn(List.of(detail)); + + // 调用:不合格品数量 = 0 + productProduceService.splitPendingAndFinishProduce(feedbackId, BigDecimal.valueOf(50), BigDecimal.ZERO); + + // 断言 1:没有新建行(不合格品数量为 0) + verify(productProduceLineService, never()).createProductProduceLine(any()); + + // 断言 2:更新了原待检行为合格 + ArgumentCaptor updateCaptor = ArgumentCaptor.forClass(MesWmProductProduceLineDO.class); + verify(productProduceLineService).updateProductProduceLine(updateCaptor.capture()); + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), updateCaptor.getValue().getQualityStatus()); + + // 断言 3:只生成了 1 条明细(全部合格品) + verify(productProduceDetailService, times(1)).createProductProduceDetail(any()); + + // 断言 4:产出单状态更新为已完成 + MesWmProductProduceDO updatedProduce = productProduceMapper.selectById(produce.getId()); + assertEquals(MesWmProductProduceStatusEnum.FINISHED.getStatus(), updatedProduce.getStatus()); + } + + @Test + public void testSplitPendingAndFinishProduce_produceNotExists() { + // 调用不存在的 feedbackId,应该抛异常 + Long feedbackId = randomLongId(); + assertThrows(Exception.class, () -> + productProduceService.splitPendingAndFinishProduce(feedbackId, BigDecimal.TEN, BigDecimal.ZERO)); + } + + @Test + public void testSplitPendingAndFinishProduce_noPendingLine() { + // 准备数据:产出单存在,但没有 PENDING 行 + Long feedbackId = randomLongId(); + MesWmProductProduceDO produce = randomPojo(MesWmProductProduceDO.class, o -> { + o.setFeedbackId(feedbackId); + o.setStatus(MesWmProductProduceStatusEnum.PREPARE.getStatus()); + }); + productProduceMapper.insert(produce); + + // mock: 虚拟线边库 + MesWmWarehouseDO wh = new MesWmWarehouseDO(); wh.setId(1L); + MesWmWarehouseLocationDO loc = new MesWmWarehouseLocationDO(); loc.setId(1L); + MesWmWarehouseAreaDO area = new MesWmWarehouseAreaDO(); area.setId(1L); + when(warehouseService.getWarehouseByCode(any())).thenReturn(wh); + when(locationService.getWarehouseLocationByCode(any())).thenReturn(loc); + when(areaService.getWarehouseAreaByCode(any())).thenReturn(area); + + // mock: 返回一条 PASS 状态的行(不是 PENDING) + MesWmProductProduceLineDO passLine = MesWmProductProduceLineDO.builder() + .id(300L).produceId(produce.getId()) + .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) + .build(); + when(productProduceLineService.getProductProduceLineListByProduceId(produce.getId())) + .thenReturn(List.of(passLine)); + + // 调用,应该抛异常(找不到 PENDING 行) + assertThrows(Exception.class, () -> + productProduceService.splitPendingAndFinishProduce(feedbackId, BigDecimal.TEN, BigDecimal.ZERO)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImplTest.java new file mode 100644 index 000000000..ee4c9a0e5 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImplTest.java @@ -0,0 +1,168 @@ +package cn.iocoder.yudao.module.mes.service.wm.productsales; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesLineMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +/** + * {@link MesWmProductSalesLineServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(MesWmProductSalesLineServiceImpl.class) +public class MesWmProductSalesLineServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmProductSalesLineServiceImpl productSalesLineService; + + @Resource + private MesWmProductSalesLineMapper productSalesLineMapper; + + @MockitoBean + private MesWmProductSalesService productSalesService; + + @MockitoBean + private MesWmProductSalesDetailService productSalesDetailService; + + @MockitoBean + private MesMdItemService itemService; + @MockitoBean + private MesWmBatchService batchService; + + @Test + public void testUpdateProductSalesLineWhenOqcFinish_pass() { + // 准备参数 + Long oqcId = randomLongId(); + Integer checkResult = MesQcCheckResultEnum.PASS.getType(); + + // mock 数据 + MesWmProductSalesLineDO lineDO = randomPojo(MesWmProductSalesLineDO.class, o -> { + o.setOqcCheckFlag(true); // 需要 OQC 检验 + o.setQualityStatus(null); // 初始为空 + }); + productSalesLineMapper.insert(lineDO); + + // 调用 + productSalesLineService.updateProductSalesLineWhenOqcFinish(lineDO.getId(), oqcId, checkResult); + + // 断言:验证行字段更新 + MesWmProductSalesLineDO updateLine = productSalesLineMapper.selectById(lineDO.getId()); + assertEquals(oqcId, updateLine.getOqcId()); + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), updateLine.getQualityStatus()); + } + + @Test + public void testUpdateProductSalesLineWhenOqcFinish_fail() { + // 准备参数 + Long oqcId = randomLongId(); + Integer checkResult = MesQcCheckResultEnum.FAIL.getType(); + + // mock 数据 + MesWmProductSalesLineDO lineDO = randomPojo(MesWmProductSalesLineDO.class, o -> { + o.setOqcCheckFlag(true); + o.setQualityStatus(null); + }); + productSalesLineMapper.insert(lineDO); + + // 调用 + productSalesLineService.updateProductSalesLineWhenOqcFinish(lineDO.getId(), oqcId, checkResult); + + // 断言:验证行字段更新 + MesWmProductSalesLineDO updateLine = productSalesLineMapper.selectById(lineDO.getId()); + assertEquals(oqcId, updateLine.getOqcId()); + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), updateLine.getQualityStatus()); + } + + @Test + public void testUpdateProductSalesLineWhenOqcFinish_cancelWhenNg() { + // 准备数据:同一出库单下 2 行,第 1 行已合格,第 2 行即将变更为不合格 + Long salesId = randomLongId(); + MesWmProductSalesLineDO line1 = randomPojo(MesWmProductSalesLineDO.class, o -> { + o.setSalesId(salesId); + o.setOqcCheckFlag(true); + o.setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus()); + }); + productSalesLineMapper.insert(line1); + + MesWmProductSalesLineDO line2 = randomPojo(MesWmProductSalesLineDO.class, o -> { + o.setSalesId(salesId); + o.setOqcCheckFlag(true); + o.setQualityStatus(null); // 待检 + }); + productSalesLineMapper.insert(line2); + + // 调用:第 2 行质检不合格 + productSalesLineService.updateProductSalesLineWhenOqcFinish( + line2.getId(), randomLongId(), MesQcCheckResultEnum.FAIL.getType()); + + // 断言:应该调用 cancelProductSales + verify(productSalesService).cancelProductSales(eq(salesId)); + } + + @Test + public void testUpdateProductSalesLineWhenOqcFinish_noCancelWhenAllPass() { + // 准备数据:同一出库单下 2 行,第 1 行已合格,第 2 行即将变更为合格 + Long salesId = randomLongId(); + MesWmProductSalesLineDO line1 = randomPojo(MesWmProductSalesLineDO.class, o -> { + o.setSalesId(salesId); + o.setOqcCheckFlag(true); + o.setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus()); + }); + productSalesLineMapper.insert(line1); + + MesWmProductSalesLineDO line2 = randomPojo(MesWmProductSalesLineDO.class, o -> { + o.setSalesId(salesId); + o.setOqcCheckFlag(true); + o.setQualityStatus(null); + }); + productSalesLineMapper.insert(line2); + + // 调用:第 2 行质检合格 + productSalesLineService.updateProductSalesLineWhenOqcFinish( + line2.getId(), randomLongId(), MesQcCheckResultEnum.PASS.getType()); + + // 断言:不应该调用 cancelProductSales + verify(productSalesService, never()).cancelProductSales(anyLong()); + } + + @Test + public void testUpdateProductSalesLineWhenOqcFinish_skipNonOqcCheckLines() { + // 准备数据:同一出库单下 2 行,第 1 行不需要 OQC 检验(oqcCheckFlag=false),第 2 行需要检验且不合格 + Long salesId = randomLongId(); + MesWmProductSalesLineDO line1 = randomPojo(MesWmProductSalesLineDO.class, o -> { + o.setSalesId(salesId); + o.setOqcCheckFlag(false); // 不需要 OQC 检验 + o.setQualityStatus(null); + }); + productSalesLineMapper.insert(line1); + + MesWmProductSalesLineDO line2 = randomPojo(MesWmProductSalesLineDO.class, o -> { + o.setSalesId(salesId); + o.setOqcCheckFlag(true); + o.setQualityStatus(null); + }); + productSalesLineMapper.insert(line2); + + // 调用:第 2 行质检不合格 + productSalesLineService.updateProductSalesLineWhenOqcFinish( + line2.getId(), randomLongId(), MesQcCheckResultEnum.FAIL.getType()); + + // 断言:第 2 行不合格 → 应该取消出库单 + verify(productSalesService).cancelProductSales(eq(salesId)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImplTest.java new file mode 100644 index 000000000..4934dcafd --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImplTest.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnissue; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnissue.MesWmReturnIssueLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnissue.MesWmReturnIssueLineMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; + +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * {@link MesWmReturnIssueLineServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(MesWmReturnIssueLineServiceImpl.class) +public class MesWmReturnIssueLineServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmReturnIssueLineServiceImpl returnIssueLineService; + + @Resource + private MesWmReturnIssueLineMapper returnIssueLineMapper; + + @MockitoBean + private MesWmReturnIssueService issueService; + + @MockitoBean + private MesMdItemService itemService; + + @Test + public void testUpdateReturnIssueLineWhenRqcFinish_allPass() { + // 准备参数:全部合格 + Integer checkResult = MesQcCheckResultEnum.PASS.getType(); + BigDecimal qualifiedQty = new BigDecimal("100"); + BigDecimal unqualifiedQty = BigDecimal.ZERO; + + // mock 数据 + MesWmReturnIssueLineDO lineDO = randomPojo(MesWmReturnIssueLineDO.class, o -> o.setQuantity(qualifiedQty)); + returnIssueLineMapper.insert(lineDO); + + // 调用(sourceDocId 传 null 不联动主表状态) + returnIssueLineService.updateReturnIssueLineWhenRqcFinish( + lineDO.getId(), null, checkResult, qualifiedQty, unqualifiedQty); + + // 断言:验证质量状态更新为合格 + MesWmReturnIssueLineDO updateLine = returnIssueLineMapper.selectById(lineDO.getId()); + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), updateLine.getQualityStatus()); + } + + @Test + public void testUpdateReturnIssueLineWhenRqcFinish_allFail() { + // 准备参数:全部不合格 + Integer checkResult = MesQcCheckResultEnum.FAIL.getType(); + BigDecimal qualifiedQty = BigDecimal.ZERO; + BigDecimal unqualifiedQty = new BigDecimal("100"); + + // mock 数据 + MesWmReturnIssueLineDO lineDO = randomPojo(MesWmReturnIssueLineDO.class, o -> o.setQuantity(unqualifiedQty)); + returnIssueLineMapper.insert(lineDO); + + // 调用 + returnIssueLineService.updateReturnIssueLineWhenRqcFinish( + lineDO.getId(), null, checkResult, qualifiedQty, unqualifiedQty); + + // 断言:验证质量状态更新为不合格 + MesWmReturnIssueLineDO updateLine = returnIssueLineMapper.selectById(lineDO.getId()); + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), updateLine.getQualityStatus()); + } + + @Test + public void testUpdateReturnIssueLineWhenRqcFinish_partialSplit() { + // 准备参数:部分合格部分不合格,触发行拆分 + Integer checkResult = MesQcCheckResultEnum.PASS.getType(); + BigDecimal qualifiedQty = new BigDecimal("80"); + BigDecimal unqualifiedQty = new BigDecimal("20"); + + // mock 数据 + MesWmReturnIssueLineDO lineDO = randomPojo(MesWmReturnIssueLineDO.class, o -> + o.setQuantity(new BigDecimal("100"))); + returnIssueLineMapper.insert(lineDO); + + // 调用 + returnIssueLineService.updateReturnIssueLineWhenRqcFinish( + lineDO.getId(), null, checkResult, qualifiedQty, unqualifiedQty); + + // 断言:原行变为合格,数量调整为合格数量 + MesWmReturnIssueLineDO originalLine = returnIssueLineMapper.selectById(lineDO.getId()); + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), originalLine.getQualityStatus()); + assertEquals(0, qualifiedQty.compareTo(originalLine.getQuantity())); + + // 断言:新增了一行不合格品 + var allLines = returnIssueLineMapper.selectListByIssueId(lineDO.getIssueId()); + assertEquals(2, allLines.size()); + MesWmReturnIssueLineDO newLine = allLines.stream() + .filter(l -> !l.getId().equals(lineDO.getId())) + .findFirst().orElse(null); + assertNotNull(newLine); + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), newLine.getQualityStatus()); + assertEquals(0, unqualifiedQty.compareTo(newLine.getQuantity())); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImplTest.java new file mode 100644 index 000000000..3ef35fe86 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImplTest.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.mes.service.wm.returnsales; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; + +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * {@link MesWmReturnSalesLineServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(MesWmReturnSalesLineServiceImpl.class) +public class MesWmReturnSalesLineServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmReturnSalesLineServiceImpl returnSalesLineService; + + @Resource + private MesWmReturnSalesLineMapper returnSalesLineMapper; + + @MockitoBean + private MesWmReturnSalesService returnSalesService; + + @MockitoBean + private MesMdItemService itemService; + + @Test + public void testUpdateReturnSalesLineWhenRqcFinish_allPass() { + // 准备参数:全部合格 + Integer checkResult = MesQcCheckResultEnum.PASS.getType(); + BigDecimal qualifiedQty = new BigDecimal("100"); + BigDecimal unqualifiedQty = BigDecimal.ZERO; + + // mock 数据 + MesWmReturnSalesLineDO lineDO = randomPojo(MesWmReturnSalesLineDO.class, o -> o.setQuantity(qualifiedQty)); + returnSalesLineMapper.insert(lineDO); + + // 调用(sourceDocId 传 null 不联动主表状态) + returnSalesLineService.updateReturnSalesLineWhenRqcFinish( + lineDO.getId(), null, checkResult, qualifiedQty, unqualifiedQty); + + // 断言:验证质量状态更新为合格 + MesWmReturnSalesLineDO updateLine = returnSalesLineMapper.selectById(lineDO.getId()); + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), updateLine.getQualityStatus()); + } + + @Test + public void testUpdateReturnSalesLineWhenRqcFinish_allFail() { + // 准备参数:全部不合格 + Integer checkResult = MesQcCheckResultEnum.FAIL.getType(); + BigDecimal qualifiedQty = BigDecimal.ZERO; + BigDecimal unqualifiedQty = new BigDecimal("100"); + + // mock 数据 + MesWmReturnSalesLineDO lineDO = randomPojo(MesWmReturnSalesLineDO.class, o -> o.setQuantity(unqualifiedQty)); + returnSalesLineMapper.insert(lineDO); + + // 调用 + returnSalesLineService.updateReturnSalesLineWhenRqcFinish( + lineDO.getId(), null, checkResult, qualifiedQty, unqualifiedQty); + + // 断言:验证质量状态更新为不合格 + MesWmReturnSalesLineDO updateLine = returnSalesLineMapper.selectById(lineDO.getId()); + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), updateLine.getQualityStatus()); + } + + @Test + public void testUpdateReturnSalesLineWhenRqcFinish_partialSplit() { + // 准备参数:部分合格部分不合格,触发行拆分 + Integer checkResult = MesQcCheckResultEnum.PASS.getType(); + BigDecimal qualifiedQty = new BigDecimal("70"); + BigDecimal unqualifiedQty = new BigDecimal("30"); + + // mock 数据 + MesWmReturnSalesLineDO lineDO = randomPojo(MesWmReturnSalesLineDO.class, o -> + o.setQuantity(new BigDecimal("100"))); + returnSalesLineMapper.insert(lineDO); + + // 调用 + returnSalesLineService.updateReturnSalesLineWhenRqcFinish( + lineDO.getId(), null, checkResult, qualifiedQty, unqualifiedQty); + + // 断言:原行变为合格,数量调整为合格数量 + MesWmReturnSalesLineDO originalLine = returnSalesLineMapper.selectById(lineDO.getId()); + assertEquals(MesWmQualityStatusEnum.PASS.getStatus(), originalLine.getQualityStatus()); + assertEquals(0, qualifiedQty.compareTo(originalLine.getQuantity())); + + // 断言:新增了一行不合格品 + var allLines = returnSalesLineMapper.selectListByReturnId(lineDO.getReturnId()); + assertEquals(2, allLines.size()); + MesWmReturnSalesLineDO newLine = allLines.stream() + .filter(l -> !l.getId().equals(lineDO.getId())) + .findFirst().orElse(null); + assertNotNull(newLine); + assertEquals(MesWmQualityStatusEnum.FAIL.getStatus(), newLine.getQualityStatus()); + assertEquals(0, unqualifiedQty.compareTo(newLine.getQuantity())); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/resources/application-unit-test.yaml b/yudao-module-mes/yudao-module-mes-server/src/test/resources/application-unit-test.yaml new file mode 100644 index 000000000..6e02b8056 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/resources/application-unit-test.yaml @@ -0,0 +1,49 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + allow-bean-definition-overriding: true # 允许 Bean 覆盖,解决 Redis 配置冲突 + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + datasource: + name: ruoyi-vue-pro + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写 + driver-class-name: org.h2.Driver + username: sa + password: + druid: + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度 + initial-size: 1 # 单元测试,配置为 1,提升启动速度 + sql: + init: + schema-locations: classpath:/sql/create_tables.sql + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + data: + redis: + host: 127.0.0.1 # 地址 + port: 16379 # 端口(单元测试,使用 16379 端口) + database: 0 # 数据库索引 + +mybatis: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao.module diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/resources/logback.xml b/yudao-module-mes/yudao-module-mes-server/src/test/resources/logback.xml new file mode 100644 index 000000000..daf756bff --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/clean.sql b/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/clean.sql new file mode 100644 index 000000000..eda0d8c6d --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/clean.sql @@ -0,0 +1,15 @@ +DELETE FROM "mes_md_auto_code_rule"; +DELETE FROM "mes_md_auto_code_part"; +DELETE FROM "mes_md_auto_code_record"; +DELETE FROM "mes_wm_arrival_notice"; +DELETE FROM "mes_wm_outsource_receipt"; +DELETE FROM "mes_qc_iqc"; +DELETE FROM "mes_qc_ipqc"; +DELETE FROM "mes_pro_feedback"; +DELETE FROM "mes_wm_product_produce"; +DELETE FROM "mes_wm_product_produce_line"; +DELETE FROM "mes_wm_product_produce_detail"; +DELETE FROM "mes_wm_item_receipt"; +DELETE FROM "mes_wm_item_receipt_line"; +DELETE FROM "mes_wm_item_receipt_detail"; +DELETE FROM "mes_wm_batch"; diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/create_tables.sql b/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/create_tables.sql new file mode 100644 index 000000000..01cfa7123 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/create_tables.sql @@ -0,0 +1,620 @@ +-- ---------------------------- +-- MES 编码规则表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_md_auto_code_rule" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) NOT NULL, + "name" varchar(64) NOT NULL, + "description" varchar(255) DEFAULT NULL, + "max_length" int DEFAULT NULL, + "padded" bit NOT NULL DEFAULT FALSE, + "padded_char" varchar(1) DEFAULT NULL, + "padded_method" tinyint DEFAULT NULL, + "status" tinyint NOT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 编码规则组成表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_md_auto_code_part" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "rule_id" bigint NOT NULL, + "sort" int NOT NULL, + "type" tinyint NOT NULL, + "length" int NOT NULL, + "date_format" varchar(20) DEFAULT NULL, + "fix_character" varchar(64) DEFAULT NULL, + "serial_start_no" int DEFAULT NULL, + "serial_step" int DEFAULT NULL, + "cycle_flag" bit DEFAULT FALSE, + "cycle_method" tinyint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 编码生成记录表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_md_auto_code_record" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "rule_id" bigint NOT NULL, + "result" varchar(64) DEFAULT NULL, + "serial_no" bigint DEFAULT NULL, + "input_char" varchar(64) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 到货通知单 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_arrival_notice" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) DEFAULT NULL, + "name" varchar(255) DEFAULT NULL, + "purchase_order_code" varchar(64) DEFAULT NULL, + "vendor_id" bigint DEFAULT NULL, + "arrival_date" timestamp DEFAULT NULL, + "contact_name" varchar(64) DEFAULT NULL, + "contact_telephone" varchar(64) DEFAULT NULL, + "status" tinyint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 外协入库单 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_outsource_receipt" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) DEFAULT NULL, + "name" varchar(255) DEFAULT NULL, + "work_order_id" bigint DEFAULT NULL, + "vendor_id" bigint DEFAULT NULL, + "receipt_date" timestamp DEFAULT NULL, + "status" tinyint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 来料检验单(IQC) +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_qc_iqc" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) DEFAULT NULL, + "name" varchar(255) DEFAULT NULL, + "template_id" bigint DEFAULT NULL, + "source_doc_type" int DEFAULT NULL, + "source_doc_id" bigint DEFAULT NULL, + "source_line_id" bigint DEFAULT NULL, + "source_doc_code" varchar(64) DEFAULT NULL, + "vendor_id" bigint DEFAULT NULL, + "vendor_batch" varchar(64) DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "received_quantity" decimal(24,6) DEFAULT NULL, + "check_quantity" decimal(24,6) DEFAULT NULL, + "qualified_quantity" decimal(24,6) DEFAULT NULL, + "unqualified_quantity" decimal(24,6) DEFAULT NULL, + "critical_rate" decimal(10,2) DEFAULT NULL, + "major_rate" decimal(10,2) DEFAULT NULL, + "minor_rate" decimal(10,2) DEFAULT NULL, + "critical_quantity" int DEFAULT NULL, + "major_quantity" int DEFAULT NULL, + "minor_quantity" int DEFAULT NULL, + "check_result" tinyint DEFAULT NULL, + "receive_date" timestamp DEFAULT NULL, + "inspect_date" timestamp DEFAULT NULL, + "inspector_user_id" bigint DEFAULT NULL, + "status" tinyint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 过程检验单(IPQC) +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_qc_ipqc" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) DEFAULT NULL, + "name" varchar(500) DEFAULT NULL, + "type" tinyint DEFAULT NULL, + "template_id" bigint DEFAULT NULL, + "source_doc_type" int DEFAULT NULL, + "source_doc_id" bigint DEFAULT NULL, + "source_line_id" bigint DEFAULT NULL, + "source_doc_code" varchar(64) DEFAULT NULL, + "work_order_id" bigint DEFAULT NULL, + "task_id" bigint DEFAULT NULL, + "workstation_id" bigint DEFAULT NULL, + "process_id" bigint DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "check_quantity" decimal(14,2) DEFAULT NULL, + "qualified_quantity" decimal(14,2) DEFAULT NULL, + "unqualified_quantity" decimal(14,2) DEFAULT NULL, + "labor_scrap_quantity" decimal(14,2) DEFAULT NULL, + "material_scrap_quantity" decimal(14,2) DEFAULT NULL, + "other_scrap_quantity" decimal(14,2) DEFAULT NULL, + "critical_rate" decimal(14,2) DEFAULT NULL, + "major_rate" decimal(14,2) DEFAULT NULL, + "minor_rate" decimal(14,2) DEFAULT NULL, + "critical_quantity" int DEFAULT NULL, + "major_quantity" int DEFAULT NULL, + "minor_quantity" int DEFAULT NULL, + "check_result" tinyint DEFAULT NULL, + "inspect_date" timestamp DEFAULT NULL, + "inspector_user_id" bigint DEFAULT NULL, + "status" tinyint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 生产报工 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_pro_feedback" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) DEFAULT NULL, + "type" tinyint DEFAULT NULL, + "channel" varchar(64) DEFAULT NULL, + "feedback_time" timestamp DEFAULT NULL, + "workstation_id" bigint DEFAULT NULL, + "route_id" bigint DEFAULT NULL, + "process_id" bigint DEFAULT NULL, + "work_order_id" bigint DEFAULT NULL, + "task_id" bigint DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "expire_date" timestamp DEFAULT NULL, + "lot_number" varchar(64) DEFAULT NULL, + "scheduled_quantity" decimal(14,2) DEFAULT NULL, + "feedback_quantity" decimal(14,2) DEFAULT NULL, + "qualified_quantity" decimal(14,2) DEFAULT NULL, + "unqualified_quantity" decimal(14,2) DEFAULT NULL, + "uncheck_quantity" decimal(14,2) DEFAULT NULL, + "labor_scrap_quantity" decimal(14,2) DEFAULT NULL, + "material_scrap_quantity" decimal(14,2) DEFAULT NULL, + "other_scrap_quantity" decimal(14,2) DEFAULT NULL, + "feedback_user_id" bigint DEFAULT NULL, + "approve_user_id" bigint DEFAULT NULL, + "status" tinyint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 生产入库单主表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_product_produce" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "work_order_id" bigint DEFAULT NULL, + "feedback_id" bigint DEFAULT NULL, + "task_id" bigint DEFAULT NULL, + "workstation_id" bigint DEFAULT NULL, + "process_id" bigint DEFAULT NULL, + "produce_date" timestamp DEFAULT NULL, + "status" int DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 生产入库单行表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_product_produce_line" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "produce_id" bigint DEFAULT NULL, + "feedback_id" bigint DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "quantity" decimal(12,2) DEFAULT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, + "expire_date" timestamp DEFAULT NULL, + "lot_number" varchar(128) DEFAULT NULL, + "quality_status" int DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 生产入库明细表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_product_produce_detail" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "produce_id" bigint DEFAULT NULL, + "line_id" bigint DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "quantity" decimal(12,2) DEFAULT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, + "warehouse_id" bigint DEFAULT NULL, + "location_id" bigint DEFAULT NULL, + "area_id" bigint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + + +-- ---------------------------- +-- MES 出货检验单(OQC) +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_qc_oqc" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) NOT NULL, + "name" varchar(500) NOT NULL, + "template_id" bigint NOT NULL, + "source_doc_id" bigint DEFAULT NULL, + "source_doc_type" int DEFAULT NULL, + "source_line_id" bigint DEFAULT NULL, + "source_doc_code" varchar(64) DEFAULT NULL, + "client_id" bigint NOT NULL, + "batch_code" varchar(64) DEFAULT NULL, + "item_id" bigint NOT NULL, + "min_check_quantity" int DEFAULT 1, + "max_unqualified_quantity" int DEFAULT 0, + "out_quantity" decimal(14,2) NOT NULL, + "check_quantity" decimal(14,2) DEFAULT NULL, + "qualified_quantity" decimal(14,2) DEFAULT 0.00, + "unqualified_quantity" decimal(14,2) DEFAULT 0.00, + "critical_rate" decimal(14,2) DEFAULT 0.00, + "major_rate" decimal(14,2) DEFAULT 0.00, + "minor_rate" decimal(14,2) DEFAULT 0.00, + "critical_quantity" int DEFAULT 0, + "major_quantity" int DEFAULT 0, + "minor_quantity" int DEFAULT 0, + "check_result" tinyint DEFAULT NULL, + "out_date" timestamp DEFAULT NULL, + "inspect_date" timestamp DEFAULT NULL, + "inspector_user_id" bigint DEFAULT NULL, + "status" tinyint NOT NULL DEFAULT 0, + "remark" varchar(500) DEFAULT '', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 退货检验单(RQC) +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_qc_rqc" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) NOT NULL, + "name" varchar(500) NOT NULL, + "template_id" bigint NOT NULL, + "source_doc_id" bigint DEFAULT NULL, + "source_doc_type" int DEFAULT NULL, + "source_line_id" bigint DEFAULT NULL, + "source_doc_code" varchar(64) DEFAULT NULL, + "type" int DEFAULT NULL, + "item_id" bigint NOT NULL, + "batch_code" varchar(128) DEFAULT NULL, + "check_quantity" decimal(14,2) DEFAULT NULL, + "qualified_quantity" decimal(14,2) DEFAULT 0.00, + "unqualified_quantity" decimal(14,2) DEFAULT 0.00, + "check_result" tinyint DEFAULT NULL, + "inspect_date" timestamp DEFAULT NULL, + "inspector_user_id" bigint DEFAULT NULL, + "status" tinyint NOT NULL DEFAULT 0, + "remark" varchar(500) DEFAULT '', + "critical_quantity" int DEFAULT 0, + "major_quantity" int DEFAULT 0, + "minor_quantity" int DEFAULT 0, + "critical_rate" decimal(5,2) DEFAULT 0.00, + "major_rate" decimal(5,2) DEFAULT 0.00, + "minor_rate" decimal(5,2) DEFAULT 0.00, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 销售出库单行 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_product_sales_line" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "sales_id" bigint NOT NULL, + "item_id" bigint NOT NULL, + "quantity" decimal(20,6) NOT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, + "material_stock_id" bigint DEFAULT NULL, + "oqc_check_flag" tinyint DEFAULT NULL, + "oqc_id" bigint DEFAULT NULL, + "quality_status" int DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 生产退料单行 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_return_issue_line" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "issue_id" bigint NOT NULL, + "material_stock_id" bigint DEFAULT NULL, + "item_id" bigint NOT NULL, + "quantity" decimal(12,2) NOT NULL DEFAULT 0.00, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, + "rqc_id" bigint DEFAULT NULL, + "rqc_check_flag" bit NOT NULL DEFAULT FALSE, + "quality_status" int DEFAULT NULL, + "remark" varchar(500) DEFAULT '', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 销售退货单行 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_return_sales_line" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "return_id" bigint NOT NULL, + "item_id" bigint NOT NULL, + "quantity" decimal(12,2) NOT NULL DEFAULT 0.00, + "batch_id" bigint DEFAULT NULL, + "rqc_id" bigint DEFAULT NULL, + "rqc_check_flag" bit NOT NULL DEFAULT FALSE, + "quality_status" int DEFAULT NULL, + "remark" varchar(500) DEFAULT '', + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 采购入库单 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_receipt" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) NOT NULL, + "name" varchar(255) DEFAULT NULL, + "iqc_id" bigint DEFAULT NULL, + "notice_id" bigint DEFAULT NULL, + "vendor_id" bigint DEFAULT NULL, + "purchase_order_code" varchar(64) DEFAULT NULL, + "receipt_date" timestamp DEFAULT NULL, + "status" tinyint NOT NULL DEFAULT 0, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 采购入库单行 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_receipt_line" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "receipt_id" bigint NOT NULL, + "arrival_notice_line_id" bigint DEFAULT NULL, + "item_id" bigint NOT NULL, + "received_quantity" decimal(14,2) DEFAULT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, + "production_date" timestamp DEFAULT NULL, + "expire_date" timestamp DEFAULT NULL, + "lot_number" varchar(128) DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 采购入库明细 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_receipt_detail" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "line_id" bigint NOT NULL, + "receipt_id" bigint NOT NULL, + "item_id" bigint NOT NULL, + "quantity" decimal(14,2) DEFAULT NULL, + "batch_id" bigint DEFAULT NULL, + "warehouse_id" bigint DEFAULT NULL, + "location_id" bigint DEFAULT NULL, + "area_id" bigint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 物料消耗记录表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_consume" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "work_order_id" bigint NOT NULL, + "task_id" bigint NOT NULL, + "workstation_id" bigint NOT NULL, + "process_id" bigint NOT NULL, + "feedback_id" bigint NOT NULL, + "consume_date" timestamp NOT NULL, + "status" tinyint NOT NULL DEFAULT 0, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 物料消耗记录行表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_consume_line" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "consume_id" bigint NOT NULL, + "item_id" bigint NOT NULL, + "quantity" decimal(14,2) NOT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(128) DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 物料消耗记录明细表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_item_consume_detail" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "consume_id" bigint NOT NULL, + "line_id" bigint NOT NULL, + "material_stock_id" bigint DEFAULT NULL, + "item_id" bigint NOT NULL, + "quantity" decimal(14,2) NOT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(128) DEFAULT NULL, + "warehouse_id" bigint NOT NULL, + "location_id" bigint NOT NULL, + "area_id" bigint NOT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 批次记录表 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_batch" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(128) DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "produce_date" timestamp DEFAULT NULL, + "expire_date" timestamp DEFAULT NULL, + "receipt_date" timestamp DEFAULT NULL, + "vendor_id" bigint DEFAULT NULL, + "client_id" bigint DEFAULT NULL, + "sales_order_code" varchar(64) DEFAULT NULL, + "purchase_order_code" varchar(64) DEFAULT NULL, + "work_order_id" bigint DEFAULT NULL, + "task_id" bigint DEFAULT NULL, + "workstation_id" bigint DEFAULT NULL, + "tool_id" bigint DEFAULT NULL, + "mold_id" bigint DEFAULT NULL, + "lot_number" varchar(128) DEFAULT NULL, + "quality_status" int DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index b7d46d08e..c06cab00d 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -113,6 +113,13 @@ + + + + + + +