From 49bad37b8a057843109b57212c7c0e6e113cfb80 Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期二, 13 十月 2026 16:20:21 +0800
Subject: [PATCH] feat(aftersales): 工单客户/联系人/物料/批次改为文本 + 问题库/回访 SQL

---
 yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/vo/ticket/AfterSaleTicketSaveReqVO.java |   16 +++-
 sql/mysql/aftersales_problem_visit_init.sql                                                                                              |   89 +++++++++++++++++++++++++++++
 yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/dataobject/ticket/AfterSaleTicketDO.java                    |    8 ++
 sql/mysql/aftersales_ticket_text_fields.sql                                                                                              |   52 +++++++++++++++++
 4 files changed, 160 insertions(+), 5 deletions(-)

diff --git a/sql/mysql/aftersales_problem_visit_init.sql b/sql/mysql/aftersales_problem_visit_init.sql
new file mode 100644
index 0000000..c0c3473
--- /dev/null
+++ b/sql/mysql/aftersales_problem_visit_init.sql
@@ -0,0 +1,89 @@
+-- =============================================
+-- 鍞悗锛氶棶棰樺簱 + 鍥炶锛堝彲閲嶅鎵ц锛�
+-- 鍚細after_sale_ticket 鍔� 6 鍒椼�乤fter_sale_problem / after_sale_visit 寤鸿〃銆侀棶棰樺簱鑿滃崟锛堢┖闂� id 602710-602716锛�
+-- =============================================
+
+-- 1. after_sale_ticket 鍔犲洖璁�/娌夋穩鐩稿叧鍒�
+SET @c := (SELECT COUNT(*) FROM information_schema.COLUMNS
+           WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'after_sale_ticket' AND COLUMN_NAME = 'visit_status');
+SET @ddl := IF(@c = 0,
+    'ALTER TABLE `after_sale_ticket`
+        ADD COLUMN `visit_status` tinyint NULL COMMENT ''鍥炶鐘舵��: 0-寰呭洖璁� 1-宸插洖璁块�氳繃'' AFTER `closed_time`,
+        ADD COLUMN `last_visit_time` datetime NULL COMMENT ''鏈�杩戜竴娆″洖璁挎椂闂�'' AFTER `visit_status`,
+        ADD COLUMN `last_visit_satisfied` bit(1) NULL COMMENT ''鏈�杩戜竴娆″洖璁挎槸鍚︽弧鎰�'' AFTER `last_visit_time`,
+        ADD COLUMN `last_visit_recurred` bit(1) NULL COMMENT ''鏈�杩戜竴娆″洖璁块棶棰樻槸鍚﹀鍙�'' AFTER `last_visit_satisfied`,
+        ADD COLUMN `problem_id` bigint NULL COMMENT ''娌夋穩闂缂栧彿'' AFTER `last_visit_recurred`,
+        ADD COLUMN `problem_no` varchar(64) NULL COMMENT ''娌夋穩闂鍗曞彿'' AFTER `problem_id`',
+    'SELECT 1');
+PREPARE s FROM @ddl; EXECUTE s; DEALLOCATE PREPARE s;
+
+-- 2. 闂搴撹〃
+CREATE TABLE IF NOT EXISTS `after_sale_problem` (
+    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '闂缂栧彿',
+    `no` varchar(64) DEFAULT NULL COMMENT '闂鍗曞彿 AP+yyyyMMdd+6浣�',
+    `title` varchar(255) DEFAULT NULL COMMENT '闂鏍囬',
+    `source_ticket_id` bigint DEFAULT NULL COMMENT '鏉ユ簮宸ュ崟缂栧彿',
+    `source_ticket_no` varchar(64) DEFAULT NULL COMMENT '鏉ユ簮宸ュ崟鍗曞彿',
+    `customer_id` bigint DEFAULT NULL COMMENT '瀹㈡埛缂栧彿',
+    `item_id` bigint DEFAULT NULL COMMENT '鐗╂枡缂栧彿',
+    `item_code` varchar(64) DEFAULT NULL COMMENT '鐗╂枡缂栫爜',
+    `item_name` varchar(255) DEFAULT NULL COMMENT '鐗╂枡鍚嶇О',
+    `batch_id` bigint DEFAULT NULL COMMENT '鐢熶骇鎵规缂栧彿',
+    `batch_code` varchar(64) DEFAULT NULL COMMENT '鐢熶骇鎵规鍙�',
+    `issue_type` tinyint DEFAULT NULL COMMENT '闂绫诲瀷',
+    `issue_category` varchar(64) DEFAULT NULL COMMENT '闂鍒嗙被',
+    `severity_level` tinyint DEFAULT NULL COMMENT '涓ラ噸绋嬪害',
+    `description` varchar(1000) DEFAULT NULL COMMENT '闂鎻忚堪',
+    `root_cause_category` tinyint DEFAULT NULL COMMENT '鏍瑰洜鍒嗙被',
+    `root_cause` text COMMENT '鏍瑰洜鍒嗘瀽',
+    `solution` text COMMENT '瑙e喅鏂规',
+    `status` tinyint NOT NULL DEFAULT 0 COMMENT '鐘舵��',
+    `owner_user_id` bigint DEFAULT NULL COMMENT '娌夋穩浜虹敤鎴风紪鍙�',
+    `publish_time` datetime DEFAULT NULL COMMENT '鍙戝竷鏃堕棿',
+    `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+    `creator` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+    `updater` varchar(64) 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`), KEY `idx_source_ticket` (`source_ticket_id`), KEY `idx_item` (`item_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='鍞悗闂搴撹〃';
+
+-- 3. 鍥炶璁板綍琛�
+CREATE TABLE IF NOT EXISTS `after_sale_visit` (
+    `id` bigint NOT NULL AUTO_INCREMENT COMMENT '鍥炶璁板綍缂栧彿',
+    `ticket_id` bigint DEFAULT NULL COMMENT '宸ュ崟缂栧彿',
+    `visit_type` tinyint DEFAULT NULL COMMENT '鍥炶鏂瑰紡: 0-鐢佃瘽 1-涓婇棬 2-杩滅▼ 3-鍏朵粬',
+    `visitor_user_id` bigint DEFAULT NULL COMMENT '鍥炶浜虹敤鎴风紪鍙�',
+    `content` varchar(1000) DEFAULT NULL COMMENT '鍥炶鍐呭',
+    `is_satisfied` bit(1) DEFAULT NULL COMMENT '鏄惁婊℃剰',
+    `is_recurred` bit(1) DEFAULT NULL COMMENT '闂鏄惁澶嶅彂',
+    `visit_time` datetime DEFAULT NULL COMMENT '鍥炶鏃堕棿',
+    `remark` varchar(500) DEFAULT NULL COMMENT '澶囨敞',
+    `creator` varchar(64) DEFAULT '' COMMENT '鍒涘缓鑰�',
+    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+    `updater` varchar(64) 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`), KEY `idx_ticket` (`ticket_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='鍞悗鍥炶璁板綍琛�';
+
+-- 4. 闂搴撹彍鍗曪紙鎸� 602587 鍞悗绠$悊 涓嬶紝绌洪棽 id 602710-602716锛�
+INSERT INTO `system_menu`
+(`id`,`name`,`permission`,`type`,`sort`,`parent_id`,`path`,`icon`,`component`,`component_name`,`status`,`visible`,`keep_alive`,`always_show`,`creator`,`create_time`,`updater`,`update_time`,`deleted`)
+VALUES
+(602710,'闂搴�','',2,3,602587,'problem','ep:collection','/aftersales/problem/index','AfterSaleProblem',0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'),
+(602711,'闂搴撴煡璇�','aftersales:problem:query',3,1,602710,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'),
+(602712,'闂搴撳垱寤�','aftersales:problem:create',3,2,602710,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'),
+(602713,'闂搴撴洿鏂�','aftersales:problem:update',3,3,602710,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'),
+(602714,'闂搴撳垹闄�','aftersales:problem:delete',3,4,602710,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'),
+(602715,'闂搴撳彂甯�','aftersales:problem:publish',3,5,602710,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'),
+(602716,'闂搴撳仠鐢�','aftersales:problem:disable',3,6,602710,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0')
+ON DUPLICATE KEY UPDATE `name`=VALUES(`name`),`permission`=VALUES(`permission`),`type`=VALUES(`type`),`parent_id`=VALUES(`parent_id`),`path`=VALUES(`path`),`component`=VALUES(`component`),`component_name`=VALUES(`component_name`),`status`=VALUES(`status`),`deleted`=b'0';
+
+INSERT INTO `system_role_menu` (`role_id`,`menu_id`,`creator`,`create_time`,`updater`,`update_time`,`deleted`)
+SELECT 1, m.menu_id, '1', NOW(), '1', NOW(), b'0'
+FROM (SELECT 602710 AS menu_id UNION ALL SELECT 602711 UNION ALL SELECT 602712 UNION ALL SELECT 602713 UNION ALL SELECT 602714 UNION ALL SELECT 602715 UNION ALL SELECT 602716) m
+WHERE NOT EXISTS (SELECT 1 FROM `system_role_menu` rm WHERE rm.`role_id`=1 AND rm.`menu_id`=m.menu_id AND rm.`deleted`=b'0');
+
+SELECT '鍞悗闂搴�/鍥炶鍒濆鍖栧畬鎴�' AS result;
diff --git a/sql/mysql/aftersales_ticket_text_fields.sql b/sql/mysql/aftersales_ticket_text_fields.sql
new file mode 100644
index 0000000..091456b
--- /dev/null
+++ b/sql/mysql/aftersales_ticket_text_fields.sql
@@ -0,0 +1,52 @@
+-- =============================================
+-- 鍞悗宸ュ崟锛氬鎴�/鑱旂郴浜�/鐗╂枡/鎵规 鏀逛负鏂囨湰瀛樺偍 + 鍏滃簳琛ラ綈宸ュ崟鎸夐挳鏉冮檺锛堝彲閲嶅鎵ц锛�
+-- =============================================
+SET @c1 := (SELECT COUNT(*) FROM information_schema.COLUMNS
+            WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'after_sale_ticket' AND COLUMN_NAME = 'customer_name');
+SET @ddl1 := IF(@c1 = 0,
+    'ALTER TABLE `after_sale_ticket` ADD COLUMN `customer_name` varchar(255) NULL COMMENT ''瀹㈡埛鍚嶇О(鏂囨湰)'' AFTER `customer_id`',
+    'SELECT 1');
+PREPARE s1 FROM @ddl1; EXECUTE s1; DEALLOCATE PREPARE s1;
+
+SET @c2 := (SELECT COUNT(*) FROM information_schema.COLUMNS
+            WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'after_sale_ticket' AND COLUMN_NAME = 'contact_name');
+SET @ddl2 := IF(@c2 = 0,
+    'ALTER TABLE `after_sale_ticket` ADD COLUMN `contact_name` varchar(255) NULL COMMENT ''鑱旂郴浜�(鏂囨湰)'' AFTER `contact_id`',
+    'SELECT 1');
+PREPARE s2 FROM @ddl2; EXECUTE s2; DEALLOCATE PREPARE s2;
+
+-- 瀹㈡埛/鑱旂郴浜烘敼涓烘枃鏈悗锛屽師澶栭敭鍒楀厑璁镐负绌�
+ALTER TABLE `after_sale_ticket` MODIFY COLUMN `customer_id` bigint NULL COMMENT '瀹㈡埛缂栧彿(鍙��)';
+ALTER TABLE `after_sale_ticket` MODIFY COLUMN `contact_id` bigint NULL COMMENT '鑱旂郴浜虹紪鍙�(鍙��)';
+
+-- 鐗╂枡/鎵规鏀逛负鏂囨湰鍚庯紝鏄庣粏鍘熷閿垪鍏佽涓虹┖
+ALTER TABLE `after_sale_ticket_item` MODIFY COLUMN `sale_order_item_id` bigint NULL COMMENT '閿�鍞鍗曡(鍙��)';
+ALTER TABLE `after_sale_ticket_item` MODIFY COLUMN `item_id` bigint NULL COMMENT 'MDM鐗╂枡缂栧彿(鍙��)';
+ALTER TABLE `after_sale_ticket_item` MODIFY COLUMN `batch_id` bigint NULL COMMENT '鎵规缂栧彿(鍙��)';
+
+-- 鍏滃簳锛氬伐鍗曟寜閽潈闄愶紙浠呭綋璇ユ潈闄愪笉瀛樺湪鏃舵墠鎻掑叆锛岄伩鍏嶄笌宸叉湁鑿滃崟閲嶅/鎾� id锛�
+INSERT INTO `system_menu`
+(`id`,`name`,`permission`,`type`,`sort`,`parent_id`,`path`,`icon`,`component`,`component_name`,`status`,`visible`,`keep_alive`,`always_show`,`creator`,`create_time`,`updater`,`update_time`,`deleted`)
+SELECT 602700,'鍞悗宸ュ崟鏂板','aftersales:ticket:create',3,1,602588,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `permission`='aftersales:ticket:create' AND `deleted`=b'0');
+INSERT INTO `system_menu`
+(`id`,`name`,`permission`,`type`,`sort`,`parent_id`,`path`,`icon`,`component`,`component_name`,`status`,`visible`,`keep_alive`,`always_show`,`creator`,`create_time`,`updater`,`update_time`,`deleted`)
+SELECT 602701,'鍞悗宸ュ崟缂栬緫','aftersales:ticket:update',3,2,602588,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `permission`='aftersales:ticket:update' AND `deleted`=b'0');
+INSERT INTO `system_menu`
+(`id`,`name`,`permission`,`type`,`sort`,`parent_id`,`path`,`icon`,`component`,`component_name`,`status`,`visible`,`keep_alive`,`always_show`,`creator`,`create_time`,`updater`,`update_time`,`deleted`)
+SELECT 602702,'鍞悗宸ュ崟鍒犻櫎','aftersales:ticket:delete',3,3,602588,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `permission`='aftersales:ticket:delete' AND `deleted`=b'0');
+INSERT INTO `system_menu`
+(`id`,`name`,`permission`,`type`,`sort`,`parent_id`,`path`,`icon`,`component`,`component_name`,`status`,`visible`,`keep_alive`,`always_show`,`creator`,`create_time`,`updater`,`update_time`,`deleted`)
+SELECT 602703,'鍞悗宸ュ崟鏌ヨ','aftersales:ticket:query',3,4,602588,'','','',NULL,0,b'1',b'1',b'1','1',NOW(),'1',NOW(),b'0'
+FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `system_menu` WHERE `permission`='aftersales:ticket:query' AND `deleted`=b'0');
+
+-- 鍏滃簳鎸夐挳 鎺堟潈缁欒秴绠�
+INSERT INTO `system_role_menu` (`role_id`,`menu_id`,`creator`,`create_time`,`updater`,`update_time`,`deleted`)
+SELECT 1, m.menu_id, '1', NOW(), '1', NOW(), b'0'
+FROM (SELECT 602700 AS menu_id UNION ALL SELECT 602701 UNION ALL SELECT 602702 UNION ALL SELECT 602703) m
+WHERE EXISTS (SELECT 1 FROM `system_menu` sm WHERE sm.`id`=m.menu_id)
+  AND NOT EXISTS (SELECT 1 FROM `system_role_menu` rm WHERE rm.`role_id`=1 AND rm.`menu_id`=m.menu_id AND rm.`deleted`=b'0');
+
+SELECT '鍞悗宸ュ崟鏂囨湰瀛楁鍒濆鍖栧畬鎴�' AS result;
diff --git a/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/vo/ticket/AfterSaleTicketSaveReqVO.java b/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/vo/ticket/AfterSaleTicketSaveReqVO.java
index 9fe2d9e..b0bb090 100644
--- a/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/vo/ticket/AfterSaleTicketSaveReqVO.java
+++ b/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/vo/ticket/AfterSaleTicketSaveReqVO.java
@@ -22,12 +22,18 @@
     @NotEmpty(message = "宸ュ崟涓婚涓嶈兘涓虹┖")
     private String name;
 
-    @Schema(description = "瀹㈡埛缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    @NotNull(message = "瀹㈡埛涓嶈兘涓虹┖")
+    @Schema(description = "瀹㈡埛缂栧彿", example = "1")
     private Long customerId;
+
+    @Schema(description = "瀹㈡埛鍚嶇О", requiredMode = Schema.RequiredMode.REQUIRED, example = "鏌愭煇鍏徃")
+    @NotEmpty(message = "瀹㈡埛涓嶈兘涓虹┖")
+    private String customerName;
 
     @Schema(description = "鑱旂郴浜虹紪鍙�", example = "1")
     private Long contactId;
+
+    @Schema(description = "鑱旂郴浜�", example = "鏉庡洓")
+    private String contactName;
 
     @Schema(description = "閿�鍞鍗曠紪鍙�", example = "1")
     private Long saleOrderId;
@@ -69,14 +75,14 @@
         @Schema(description = "閿�鍞鍗曡缂栧彿", example = "1")
         private Long saleOrderItemId;
 
-        @Schema(description = "MDM鐗╂枡缂栧彿", requiredMode = Schema.RequiredMode.REQUIRED)
-        @NotNull(message = "鐗╂枡涓嶈兘涓虹┖")
+        @Schema(description = "MDM鐗╂枡缂栧彿", example = "1")
         private Long itemId;
 
         @Schema(description = "鐗╂枡缂栫爜", example = "MAT-001")
         private String itemCode;
 
-        @Schema(description = "鐗╂枡鍚嶇О", example = "鐢靛瓙鍏冨櫒浠�")
+        @Schema(description = "鐗╂枡鍚嶇О", requiredMode = Schema.RequiredMode.REQUIRED, example = "鐢靛瓙鍏冨櫒浠�")
+        @NotEmpty(message = "鐗╂枡涓嶈兘涓虹┖")
         private String itemName;
 
         @Schema(description = "鐢熶骇鎵规缂栧彿", example = "1")
diff --git a/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/dataobject/ticket/AfterSaleTicketDO.java b/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/dataobject/ticket/AfterSaleTicketDO.java
index 4f71c3e..ad06eb6 100644
--- a/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/dataobject/ticket/AfterSaleTicketDO.java
+++ b/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/dal/dataobject/ticket/AfterSaleTicketDO.java
@@ -41,10 +41,18 @@
      */
     private Long customerId;
     /**
+     * 瀹㈡埛鍚嶇О(鏂囨湰锛屽彲鑷敱濉啓)
+     */
+    private String customerName;
+    /**
      * 鑱旂郴浜虹紪鍙凤紝鍏宠仈 crm_contact.id
      */
     private Long contactId;
     /**
+     * 鑱旂郴浜�(鏂囨湰锛屽彲鑷敱濉啓)
+     */
+    private String contactName;
+    /**
      * 閿�鍞鍗曠紪鍙凤紝鍏宠仈 erp_sale_order.id
      */
     private Long saleOrderId;

--
Gitblit v1.9.3