migration_20260715_crm_price_letter.sql 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. -- ============================================================
  2. -- CRM 调价函管理:建表 + 字典 + 菜单(合同管理下方)
  3. -- 执行前可先备份 sys_menu;可重复执行(菜单/字典做了 NOT EXISTS 防护)
  4. -- ============================================================
  5. -- 1) 业务表
  6. CREATE TABLE IF NOT EXISTS `crm_price_letter` (
  7. `id` varchar(64) NOT NULL COMMENT '主键ID(UUID)',
  8. `letter_type` varchar(20) NOT NULL COMMENT '类型 receive接受/send发出',
  9. `adjust_date` date NOT NULL COMMENT '调价日期',
  10. `customer_id` varchar(64) NOT NULL COMMENT '客户ID(crm_customer.id)',
  11. `customer_name` varchar(200) DEFAULT NULL COMMENT '客户名称(冗余)',
  12. `product_id` varchar(64) NOT NULL COMMENT '产品ID(crm_product.id)',
  13. `product_name` varchar(200) DEFAULT NULL COMMENT '产品名称(冗余)',
  14. `price` decimal(15,2) NOT NULL COMMENT '调整后现金价格(元)',
  15. `bill_price` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '调整后汇票价格(元)',
  16. `content` mediumtext COMMENT '发出类富文本HTML;接受类为空',
  17. `attachment_urls` varchar(4000) DEFAULT NULL COMMENT '附件URL(逗号分隔,兼容上传组件)',
  18. `status` varchar(20) NOT NULL DEFAULT 'normal' COMMENT '状态 normal正常/invalid已作废',
  19. `invalid_reason` varchar(200) DEFAULT NULL COMMENT '作废原因',
  20. `invalid_time` datetime DEFAULT NULL COMMENT '作废时间',
  21. `invalid_by` varchar(64) DEFAULT NULL COMMENT '作废人ID',
  22. `tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
  23. `order_num` int(11) DEFAULT NULL COMMENT '排序号',
  24. `remark` varchar(512) DEFAULT NULL COMMENT '备注',
  25. `create_by` varchar(64) DEFAULT NULL COMMENT '创建人ID',
  26. `create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
  27. `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  28. `update_by` varchar(64) DEFAULT NULL COMMENT '更新人ID',
  29. `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  30. `del_flag` smallint(6) NOT NULL DEFAULT '0' COMMENT '删除标记(0存在 1删除)',
  31. PRIMARY KEY (`id`) USING BTREE,
  32. KEY `idx_price_letter_tenant` (`tenant_no`) USING BTREE,
  33. KEY `idx_price_letter_type` (`letter_type`) USING BTREE,
  34. KEY `idx_price_letter_status` (`status`) USING BTREE,
  35. KEY `idx_price_letter_customer` (`customer_id`) USING BTREE,
  36. KEY `idx_price_letter_product` (`product_id`) USING BTREE,
  37. KEY `idx_price_letter_adjust_date` (`adjust_date`) USING BTREE,
  38. KEY `idx_price_letter_create_time` (`create_time`) USING BTREE
  39. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-调价函档案(独立,不关联合同/报价单)';
  40. -- 2) 字典类型
  41. INSERT INTO `sys_dict_type` (
  42. `id`, `dict_name`, `dict_type`, `tenant_no`, `order_num`, `remark`,
  43. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  44. )
  45. SELECT
  46. 'CRM_DTYPE_PRICE_LETTER_TYPE', '调价函类型', 'crm_price_letter_type', 'shanxia2.0', 90, '接受/发出',
  47. 'system', '', NOW(), NULL, NOW(), 0
  48. FROM DUAL
  49. WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_type` WHERE `id` = 'CRM_DTYPE_PRICE_LETTER_TYPE' OR `dict_type` = 'crm_price_letter_type');
  50. INSERT INTO `sys_dict_type` (
  51. `id`, `dict_name`, `dict_type`, `tenant_no`, `order_num`, `remark`,
  52. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  53. )
  54. SELECT
  55. 'CRM_DTYPE_PRICE_LETTER_STATUS', '调价函状态', 'crm_price_letter_status', 'shanxia2.0', 91, '正常/已作废',
  56. 'system', '', NOW(), NULL, NOW(), 0
  57. FROM DUAL
  58. WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_type` WHERE `id` = 'CRM_DTYPE_PRICE_LETTER_STATUS' OR `dict_type` = 'crm_price_letter_status');
  59. -- 3) 字典数据
  60. INSERT INTO `sys_dict_data` (
  61. `id`, `dict_label`, `dict_value`, `tag_type`, `dict_type`, `tenant_no`, `order_num`,
  62. `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  63. )
  64. SELECT 'CRM_DDATA_PRICE_LETTER_TYPE_01', '接受调价函', 'receive', 'warning', 'crm_price_letter_type', 'shanxia2.0', 1,
  65. NULL, 'system', '', NOW(), NULL, NOW(), 0
  66. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_data` WHERE `id` = 'CRM_DDATA_PRICE_LETTER_TYPE_01');
  67. INSERT INTO `sys_dict_data` (
  68. `id`, `dict_label`, `dict_value`, `tag_type`, `dict_type`, `tenant_no`, `order_num`,
  69. `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  70. )
  71. SELECT 'CRM_DDATA_PRICE_LETTER_TYPE_02', '发出调价函', 'send', 'success', 'crm_price_letter_type', 'shanxia2.0', 2,
  72. NULL, 'system', '', NOW(), NULL, NOW(), 0
  73. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_data` WHERE `id` = 'CRM_DDATA_PRICE_LETTER_TYPE_02');
  74. INSERT INTO `sys_dict_data` (
  75. `id`, `dict_label`, `dict_value`, `tag_type`, `dict_type`, `tenant_no`, `order_num`,
  76. `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  77. )
  78. SELECT 'CRM_DDATA_PRICE_LETTER_STATUS_01', '正常', 'normal', 'success', 'crm_price_letter_status', 'shanxia2.0', 1,
  79. NULL, 'system', '', NOW(), NULL, NOW(), 0
  80. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_data` WHERE `id` = 'CRM_DDATA_PRICE_LETTER_STATUS_01');
  81. INSERT INTO `sys_dict_data` (
  82. `id`, `dict_label`, `dict_value`, `tag_type`, `dict_type`, `tenant_no`, `order_num`,
  83. `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  84. )
  85. SELECT 'CRM_DDATA_PRICE_LETTER_STATUS_02', '已作废', 'invalid', 'danger', 'crm_price_letter_status', 'shanxia2.0', 2,
  86. NULL, 'system', '', NOW(), NULL, NOW(), 0
  87. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_dict_data` WHERE `id` = 'CRM_DDATA_PRICE_LETTER_STATUS_02');
  88. -- 4) 菜单排序:合同管理(order_num=6) 之后顺延
  89. UPDATE `sys_menu`
  90. SET `order_num` = `order_num` + 1,
  91. `update_time` = NOW()
  92. WHERE `parent_id` = 'CRM00000000000000000000000000001'
  93. AND `order_num` >= 7
  94. AND `del_flag` = 0
  95. AND NOT EXISTS (
  96. SELECT 1 FROM (
  97. SELECT id FROM `sys_menu` WHERE `id` = 'CRM3000000000000000000000000030' AND `del_flag` = 0
  98. ) t
  99. );
  100. -- 5) 菜单 + 按钮(无 remove,含 print/void)
  101. INSERT INTO `sys_menu` (
  102. `id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
  103. `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
  104. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  105. )
  106. SELECT
  107. 'CRM3000000000000000000000000030', '调价函管理', 'CRM00000000000000000000000000001', 'C',
  108. 'price-letter', '/crm/price-letter/index', 'crm:priceLetter:list',
  109. 1, '1', '1', 'shanxia2.0', 7, '独立调价函档案:接受(附件)/发出(富文本+可选附件);不关联合同与报价单',
  110. 'system', '', NOW(), NULL, NOW(), 0
  111. FROM DUAL
  112. WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'CRM3000000000000000000000000030');
  113. INSERT INTO `sys_menu` (
  114. `id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
  115. `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
  116. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  117. )
  118. SELECT 'CRM3000000000000000000000000031', '调价函新增', 'CRM3000000000000000000000000030', 'F', '', NULL, 'crm:priceLetter:add',
  119. 1, '1', '1', 'shanxia2.0', 1, NULL, 'system', '', NOW(), NULL, NOW(), 0
  120. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'CRM3000000000000000000000000031');
  121. INSERT INTO `sys_menu` (
  122. `id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
  123. `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
  124. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  125. )
  126. SELECT 'CRM3000000000000000000000000032', '调价函编辑', 'CRM3000000000000000000000000030', 'F', '', NULL, 'crm:priceLetter:edit',
  127. 1, '1', '1', 'shanxia2.0', 2, NULL, 'system', '', NOW(), NULL, NOW(), 0
  128. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'CRM3000000000000000000000000032');
  129. INSERT INTO `sys_menu` (
  130. `id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
  131. `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
  132. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  133. )
  134. SELECT 'CRM3000000000000000000000000034', '调价函查看', 'CRM3000000000000000000000000030', 'F', '', NULL, 'crm:priceLetter:query',
  135. 1, '1', '1', 'shanxia2.0', 3, NULL, 'system', '', NOW(), NULL, NOW(), 0
  136. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'CRM3000000000000000000000000034');
  137. INSERT INTO `sys_menu` (
  138. `id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
  139. `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
  140. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  141. )
  142. SELECT 'CRM3000000000000000000000000035', '调价函打印', 'CRM3000000000000000000000000030', 'F', '', NULL, 'crm:priceLetter:print',
  143. 1, '1', '1', 'shanxia2.0', 4, NULL, 'system', '', NOW(), NULL, NOW(), 0
  144. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'CRM3000000000000000000000000035');
  145. INSERT INTO `sys_menu` (
  146. `id`, `menu_name`, `parent_id`, `menu_type`, `path`, `component`, `perms`,
  147. `is_frame`, `visible`, `status`, `tenant_no`, `order_num`, `remark`,
  148. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  149. )
  150. SELECT 'CRM3000000000000000000000000036', '调价函作废', 'CRM3000000000000000000000000030', 'F', '', NULL, 'crm:priceLetter:void',
  151. 1, '1', '1', 'shanxia2.0', 5, NULL, 'system', '', NOW(), NULL, NOW(), 0
  152. FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `sys_menu` WHERE `id` = 'CRM3000000000000000000000000036');
  153. -- 6) 若曾误写「删除」按钮,统一软删(仅作废,无物理删除能力)
  154. UPDATE `sys_menu`
  155. SET `del_flag` = 1,
  156. `update_time` = NOW(),
  157. `remark` = CONCAT(IFNULL(`remark`, ''), ' [disabled: use void]')
  158. WHERE `id` = 'CRM3000000000000000000000000033'
  159. AND `del_flag` = 0;
  160. -- 7) 将调价函菜单/按钮授权给已拥有「合同管理」的角色(可重复执行)
  161. INSERT INTO `sys_role_menu` (
  162. `id`, `role_id`, `menu_id`, `tenant_no`, `order_num`, `remark`,
  163. `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`
  164. )
  165. SELECT DISTINCT
  166. CONCAT('CRM_RM_PL_', SUBSTRING(MD5(CONCAT(rm.role_id, '-', m.id)), 1, 20)),
  167. rm.role_id,
  168. m.id,
  169. COALESCE(NULLIF(rm.tenant_no, ''), 'shanxia2.0'),
  170. 0,
  171. 'auto grant price-letter with contract',
  172. 'system',
  173. '',
  174. NOW(),
  175. NULL,
  176. NOW(),
  177. 0
  178. FROM `sys_role_menu` rm
  179. JOIN `sys_menu` m ON m.id IN (
  180. 'CRM3000000000000000000000000030',
  181. 'CRM3000000000000000000000000031',
  182. 'CRM3000000000000000000000000032',
  183. 'CRM3000000000000000000000000034',
  184. 'CRM3000000000000000000000000035',
  185. 'CRM3000000000000000000000000036'
  186. ) AND m.del_flag = 0
  187. WHERE rm.menu_id = 'CRM3000000000000000000000000020'
  188. AND rm.del_flag = 0
  189. AND NOT EXISTS (
  190. SELECT 1 FROM `sys_role_menu` x
  191. WHERE x.role_id = rm.role_id AND x.menu_id = m.id AND x.del_flag = 0
  192. );