diff --git a/pom.xml b/pom.xml index dae40f3dc..828fb89c8 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ + yudao-module-crm diff --git a/sql/mysql/crm.sql b/sql/mysql/crm.sql new file mode 100644 index 000000000..de7922d24 --- /dev/null +++ b/sql/mysql/crm.sql @@ -0,0 +1,65 @@ +SET NAMES utf8mb4; + + + + +-- ---------------------------- +-- 回款表 +-- ---------------------------- +DROP TABLE IF EXISTS `crm_receivable`; +CREATE TABLE `crm_receivable` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '回款编号', + `plan_id` bigint(20) NULL DEFAULT NULL COMMENT '回款计划ID', + `customer_id` bigint(20) NULL DEFAULT NULL COMMENT '客户ID', + `contract_id` bigint(20) NULL DEFAULT NULL COMMENT '合同ID', + `check_status` tinyint(4) NULL DEFAULT NULL COMMENT '审批状态', + `process_instance_id` bigint(20) NULL DEFAULT NULL COMMENT '工作流编号', + `return_time` datetime NULL DEFAULT NULL COMMENT '回款日期', + `return_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '回款方式', + `price` decimal(10, 2) NULL DEFAULT NULL COMMENT '回款金额', + `owner_user_id` bigint(20) NULL DEFAULT NULL COMMENT '负责人的用户编号', + `batch_id` bigint(20) NULL DEFAULT NULL COMMENT '批次', + `sort` int(11) NULL DEFAULT NULL COMMENT '显示顺序', + `data_scope` tinyint(4) NULL DEFAULT 1 COMMENT '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', + `data_scope_dept_ids` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '数据范围(指定部门数组)', + `status` tinyint(4) NOT NULL COMMENT '状态(0正常 1停用)', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `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 '是否删除', + `tenant_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '回款管理' ROW_FORMAT = DYNAMIC; + + +-- ---------------------------- +-- 回款计划表 +-- ---------------------------- +DROP TABLE IF EXISTS `crm_receivable_plan`; +CREATE TABLE `crm_receivable_plan` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID', + `index_no` bigint(20) NULL DEFAULT NULL COMMENT '期数', + `receivable_id` bigint(20) NULL DEFAULT NULL COMMENT '回款ID', + `status` tinyint(4) NOT NULL COMMENT '完成状态', + `check_status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '审批状态', + `process_instance_id` bigint(20) NULL DEFAULT NULL COMMENT '工作流编号', + `price` decimal(10, 2) NULL DEFAULT NULL COMMENT '计划回款金额', + `return_time` datetime NULL DEFAULT NULL COMMENT '计划回款日期', + `remind_days` bigint(20) NULL DEFAULT NULL COMMENT '提前几天提醒', + `remind_time` datetime NULL DEFAULT NULL COMMENT '提醒日期', + `customer_id` bigint(20) NULL DEFAULT NULL COMMENT '客户ID', + `contract_id` bigint(20) NULL DEFAULT NULL COMMENT '合同ID', + `owner_user_id` bigint(20) NULL DEFAULT NULL COMMENT '负责人', + `sort` int(11) NULL DEFAULT NULL COMMENT '显示顺序', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '备注', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `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 '是否删除', + `tenant_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '回款计划' ROW_FORMAT = DYNAMIC; diff --git a/sql/mysql/crm_data.sql b/sql/mysql/crm_data.sql new file mode 100644 index 000000000..2d742698d --- /dev/null +++ b/sql/mysql/crm_data.sql @@ -0,0 +1,20 @@ + +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (184, '回款管理审批状态', 'crm_receivable_check_status', 0, '回款管理审批状态(0 未审核 1 审核通过 2 审核拒绝 3 审核中 4 已撤回)', '1', '2023-10-18 21:44:24', '1', '2023-10-18 21:44:24', 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 (185, '回款管理-回款方式', 'crm_return_type', 0, '回款管理-回款方式', '1', '2023-10-18 21:54:10', '1', '2023-10-18 21:54:10', b'0', '1970-01-01 00:00:00'); + + +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1389, 0, '未审核', '0', 'crm_receivable_check_status', 0, 'default', '', '0 未审核 ', '1', '2023-10-18 21:46:00', '1', '2023-10-18 21:47:16', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1390, 1, '审核通过', '1', 'crm_receivable_check_status', 0, 'default', '', '1 审核通过', '1', '2023-10-18 21:46:18', '1', '2023-10-18 21:47:08', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1391, 2, '审核拒绝', '2', 'crm_receivable_check_status', 0, 'default', '', ' 2 审核拒绝', '1', '2023-10-18 21:46:58', '1', '2023-10-18 21:47: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 (1392, 3, '审核中', '3', 'crm_receivable_check_status', 0, 'default', '', ' 3 审核中', '1', '2023-10-18 21:47:35', '1', '2023-10-18 21:47: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 (1393, 4, '已撤回', '4', 'crm_receivable_check_status', 0, 'default', '', ' 4 已撤回', '1', '2023-10-18 21:47:46', '1', '2023-10-18 21:47: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 (1394, 1, '支票', '1', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:29', '1', '2023-10-18 21:54: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 (1395, 2, '现金', '2', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:41', '1', '2023-10-18 21:54: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 (1396, 3, '邮政汇款', '3', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:54:53', '1', '2023-10-18 21:54: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 (1397, 4, '电汇', '4', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:07', '1', '2023-10-18 21:55: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 (1398, 5, '网上转账', '5', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:24', '1', '2023-10-18 21:55: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 (1399, 6, '支付宝', '6', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:38', '1', '2023-10-18 21:55: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 (1400, 7, '微信支付', '7', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:55:53', '1', '2023-10-18 21:55: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 (1401, 8, '其他', '8', 'crm_return_type', 0, 'default', '', '', '1', '2023-10-18 21:56:06', '1', '2023-10-18 21:56:06', b'0'); + + diff --git a/sql/mysql/crm_menu.sql b/sql/mysql/crm_menu.sql new file mode 100644 index 000000000..e69de29bb diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index 0022811bb..b26915d5e 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -11,7 +11,7 @@ Target Server Version : 80034 File Encoding : 65001 - Date: 24/10/2023 20:48:38 + Date: 29/10/2023 19:22:42 */ SET NAMES utf8mb4; @@ -341,7 +341,8 @@ CREATE TABLE `infra_api_access_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_create_time`(`create_time` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 35832 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'API 访问日志表'; -- ---------------------------- @@ -384,7 +385,7 @@ CREATE TABLE `infra_api_error_log` ( `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 = 1745 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 1750 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -538,7 +539,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 = 1108 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1109 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -587,7 +588,7 @@ CREATE TABLE `infra_file_content` ( `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 = 201 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 202 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file_content @@ -768,7 +769,7 @@ CREATE TABLE `member_experience_record` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '会员经验记录-用户编号', INDEX `idx_user_biz_type`(`user_id` ASC, `biz_type` ASC) USING BTREE COMMENT '会员经验记录-用户业务类型' -) ENGINE = InnoDB AUTO_INCREMENT = 41 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员经验记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 42 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员经验记录'; -- ---------------------------- -- Records of member_experience_record @@ -884,7 +885,7 @@ CREATE TABLE `member_level_record` ( `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_user_id`(`user_id` ASC) USING BTREE COMMENT '会员等级记录-用户编号' -) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会员等级记录'; -- ---------------------------- -- Records of member_level_record @@ -914,7 +915,7 @@ CREATE TABLE `member_point_record` ( PRIMARY KEY (`id`) USING BTREE, INDEX `index_userId`(`user_id` ASC) USING BTREE, INDEX `index_title`(`title` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 60 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户积分记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 61 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户积分记录'; -- ---------------------------- -- Records of member_point_record @@ -1434,6 +1435,39 @@ 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 (1395, 22, '订单积分奖励(整单取消)', '22', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:42:55', '1', '2023-10-11 07:43:01', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1396, 23, '订单积分奖励(单个退款)', '23', 'member_point_biz_type', 0, 'default', '', '', '1', '2023-10-11 07:43:16', '1', '2023-10-11 07:43:16', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1397, 13, '下单奖励(单个退款)', '13', 'member_experience_biz_type', 0, 'warning', '', '', '1', '2023-10-11 07:45:24', '1', '2023-10-11 07:45: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 (1402, 1, 'A 农、林、牧、渔业', '1', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:15', '1', '2023-10-28 23:02: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 (1403, 2, 'B 采矿业', '2', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:29', '1', '2023-10-28 23:02: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 (1404, 3, 'C 制造业', '3', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:41', '1', '2023-10-28 23:02: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 (1405, 4, 'D 电力、热力、燃气及水生产和供应业', '4', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:02:54', '1', '2023-10-28 23:02: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 (1406, 5, 'E 建筑业', '5', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:03', '1', '2023-10-28 23:03: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 (1407, 6, 'F 批发和零售业', '6', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:13', '1', '2023-10-28 23:03: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 (1408, 7, 'G 交通运输、仓储和邮政业', '7', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:27', '1', '2023-10-28 23:03: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 (1409, 8, 'H 住宿和餐饮业', '8', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:37', '1', '2023-10-28 23:03: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 (1410, 9, 'I 信息传输、软件和信息技术服务业', '9', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:47', '1', '2023-10-28 23:03: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 (1411, 10, 'J 金融业', '10', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:03:57', '1', '2023-10-28 23: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 (1412, 11, 'K 房地产业', '11', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:04:15', '1', '2023-10-28 23:04: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 (1413, 12, 'L 租赁和商务服务业', '12', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:04:33', '1', '2023-10-28 23:04: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 (1414, 13, 'M 科学研究和技术服务业', '13', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:04:43', '1', '2023-10-28 23:04: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 (1415, 14, 'N 水利、环境和公共设施管理业', '14', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:04:53', '1', '2023-10-28 23:04: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 (1416, 15, 'O 居民服务、修理和其他服务业', '15', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:05:05', '1', '2023-10-28 23:05: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 (1417, 16, 'P 教育', '16', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:05:15', '1', '2023-10-28 23:05: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 (1418, 17, 'Q 卫生和社会工作', '17', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:05:44', '1', '2023-10-28 23:05: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 (1419, 18, 'R 文化、体育和娱乐业', '18', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:05:55', '1', '2023-10-28 23:05: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 (1420, 19, 'S 公共管理、社会保障和社会组织', '19', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:06:05', '1', '2023-10-28 23:06: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 (1421, 20, 'T 国际组织', '20', 'crm_customer_industry', 0, 'default', '', '', '1', '2023-10-28 23:06:15', '1', '2023-10-28 23:06: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 (1422, 1, 'A (重点客户)', '1', 'crm_customer_level', 0, 'primary', '', '', '1', '2023-10-28 23:07:13', '1', '2023-10-28 23:07: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 (1423, 2, 'B (普通客户)', '2', 'crm_customer_level', 0, 'info', '', '', '1', '2023-10-28 23:07:35', '1', '2023-10-28 23:07: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 (1424, 3, 'C (非优先客户)', '3', 'crm_customer_level', 0, 'default', '', '', '1', '2023-10-28 23:07:53', '1', '2023-10-28 23:07: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 (1425, 1, '促销', '1', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:29', '1', '2023-10-28 23:08: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 (1426, 2, '搜索引擎', '2', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:39', '1', '2023-10-28 23:08:39', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1427, 3, '广告', '3', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:47', '1', '2023-10-28 23:08: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 (1428, 4, '转介绍', '4', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:08:58', '1', '2023-10-28 23:08: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 (1429, 5, '线上注册', '5', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:12', '1', '2023-10-28 23:09: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 (1430, 6, '线上咨询', '6', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:22', '1', '2023-10-28 23:09: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 (1431, 7, '预约上门', '7', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:09:39', '1', '2023-10-28 23:09:39', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1432, 8, '陌拜', '8', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:04', '1', '2023-10-28 23:10: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 (1433, 9, '电话咨询', '9', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:18', '1', '2023-10-28 23:10: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 (1434, 10, '邮件咨询', '10', 'crm_customer_source', 0, 'default', '', '', '1', '2023-10-28 23:10:33', '1', '2023-10-28 23:10:33', b'0'); COMMIT; -- ---------------------------- @@ -1454,7 +1488,7 @@ CREATE TABLE `system_dict_type` ( `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 185 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; +) ENGINE = InnoDB AUTO_INCREMENT = 601 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; -- ---------------------------- -- Records of system_dict_type @@ -1528,6 +1562,9 @@ 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 (182, '佣金提现银行', 'brokerage_bank_name', 0, NULL, '', '2023-09-28 02:46:05', '', '2023-09-28 02:46:05', b'0', NULL); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (183, '砍价记录的状态', 'promotion_bargain_record_status', 0, '', '1', '2023-10-05 10:41:08', '1', '2023-10-05 10:41:08', 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 (184, '拼团记录的状态', 'promotion_combination_record_status', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-10-08 07:24:25', 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 (186, '客户所属行业', 'crm_customer_industry', 0, 'CRM 客户所属行业', '1', '2023-10-28 22:57:07', '1', '2023-10-28 15:11:16', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (187, '客户等级', 'crm_customer_level', 0, 'CRM 客户等级', '1', '2023-10-28 22:59:12', '1', '2023-10-28 15:11:16', b'0', NULL); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (188, '客户来源', 'crm_customer_source', 0, 'CRM 客户来源', '1', '2023-10-28 23:00:34', '1', '2023-10-28 15:11:16', b'0', NULL); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (600, 'Banner Position', 'promotion_banner_position', 0, '', '1', '2023-10-08 07:24:25', '1', '2023-10-08 07:24:25', b'0', '1970-01-01 00:00:00'); COMMIT; @@ -1577,7 +1614,7 @@ CREATE TABLE `system_login_log` ( `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 = 2620 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 2626 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -2203,6 +2240,49 @@ 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 (2388, '商城首页', '', 2, 1, 2362, 'home', 'ep:home-filled', 'mall/home/index', 'MallHome', 0, b'1', b'1', b'1', '', '2023-10-16 12:10:33', '', '2023-10-16 12:10: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 (2389, '核销订单', '', 2, 2, 2166, 'pick-up-order', 'ep:list', 'mall/trade/delivery/pickUpOrder/index', 'PickUpOrder', 0, b'1', b'1', b'1', '', '2023-10-19 16:09:51', '', '2023-10-19 16:09:51', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2390, '优惠活动', '', 1, 99, 2030, 'youhui', 'ep:aim', '', '', 0, b'1', b'1', b'1', '1', '2023-10-21 19:23:49', '1', '2023-10-21 19:23: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 (2391, '客户管理', '', 2, 0, 2397, 'customer', 'fa:address-book-o', 'crm/customer/index', 'CrmCustomer', 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '1', '2023-10-29 17:11: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 (2392, '客户查询', 'crm:customer:query', 3, 1, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04: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 (2393, '客户创建', 'crm:customer:create', 3, 2, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04: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 (2394, '客户更新', 'crm:customer:update', 3, 3, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04: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 (2395, '客户删除', 'crm:customer:delete', 3, 4, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04: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 (2396, '客户导出', 'crm:customer:export', 3, 5, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04: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 (2397, '客户管理系统', '', 1, 200, 0, '/crm', 'ep:avatar', '', '', 0, b'1', b'1', b'1', '1', '2023-10-29 17:08:30', '1', '2023-10-29 17:08: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 (2398, '合同管理', '', 2, 1, 2397, 'contract', 'ep:notebook', 'crm/contract/index', 'CrmContract', 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '1', '2023-10-29 18: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 (2399, '合同查询', 'crm:contract:query', 3, 1, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50: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 (2400, '合同创建', 'crm:contract:create', 3, 2, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50: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 (2401, '合同更新', 'crm:contract:update', 3, 3, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50: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 (2402, '合同删除', 'crm:contract:delete', 3, 4, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50: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 (2403, '合同导出', 'crm:contract:export', 3, 5, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50: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 (2404, '线索管理', '', 2, 0, 2397, 'clue', 'fa:pagelines', 'crm/clue/index', 'CrmClue', 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '1', '2023-10-29 19:08: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 (2405, '线索查询', 'crm:clue:query', 3, 1, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06: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 (2406, '线索创建', 'crm:clue:create', 3, 2, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06: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 (2407, '线索更新', 'crm:clue:update', 3, 3, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06: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 (2408, '线索删除', 'crm:clue:delete', 3, 4, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06: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 (2409, '线索导出', 'crm:clue:export', 3, 5, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06: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 (2410, '商机管理', '', 2, 0, 2397, 'business', 'fa:bus', 'crm/business/index', 'CrmBusiness', 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '1', '2023-10-29 19: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 (2411, '商机查询', 'crm:business:query', 3, 1, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12: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 (2412, '商机创建', 'crm:business:create', 3, 2, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12: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 (2413, '商机更新', 'crm:business:update', 3, 3, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12: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 (2414, '商机删除', 'crm:business:delete', 3, 4, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12: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 (2415, '商机导出', 'crm:business:export', 3, 5, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12: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 (2416, '联系人管理', '', 2, 0, 2397, 'contact', 'fa:address-book-o', 'crm/contact/index', 'Contact', 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '1', '2023-10-29 19:15: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 (2417, '联系人查询', 'crm:contact:query', 3, 1, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14: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 (2418, '联系人创建', 'crm:contact:create', 3, 2, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14: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 (2419, '联系人更新', 'crm:contact:update', 3, 3, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14: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 (2420, '联系人删除', 'crm:contact:delete', 3, 4, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14: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 (2421, '联系人导出', 'crm:contact:export', 3, 5, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14: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 (2422, '回款管理', '', 2, 0, 2397, 'receivable', 'ep:money', 'crm/receivable/index', 'CrmReceivable', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2023-10-29 19:18: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 (2423, '回款管理查询', 'crm:receivable:query', 3, 1, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2424, '回款管理创建', 'crm:receivable:create', 3, 2, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2425, '回款管理更新', 'crm:receivable:update', 3, 3, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2426, '回款管理删除', 'crm:receivable:delete', 3, 4, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2427, '回款管理导出', 'crm:receivable:export', 3, 5, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2428, '回款计划管理', '', 2, 0, 2397, 'receivable-plan', 'fa:money', 'crm/receivablePlan/index', 'CrmReceivablePlan', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2023-10-29 19:19: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 (2429, '回款计划查询', 'crm:receivable-plan:query', 3, 1, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2430, '回款计划创建', 'crm:receivable-plan:create', 3, 2, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2431, '回款计划更新', 'crm:receivable-plan:update', 3, 3, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2432, '回款计划删除', 'crm:receivable-plan:delete', 3, 4, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18: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 (2433, '回款计划导出', 'crm:receivable-plan:export', 3, 5, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); COMMIT; -- ---------------------------- @@ -2320,8 +2400,10 @@ CREATE TABLE `system_oauth2_access_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 = 3130 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; + 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 = 3137 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -2443,7 +2525,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( `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 = 1089 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1094 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -2483,7 +2565,7 @@ CREATE TABLE `system_operate_log` ( `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 = 8757 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 8766 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; -- ---------------------------- -- Records of system_operate_log @@ -3834,7 +3916,7 @@ CREATE TABLE `system_users` ( -- 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$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2023-10-24 20:20:54', 'admin', '2021-01-05 17:03:47', NULL, '2023-10-24 20:20:54', 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$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '15612345678', 1, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2023-10-29 17:06:12', 'admin', '2021-01-05 17:03:47', NULL, '2023-10-29 17:06:12', 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$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03: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 (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-07-08 01:26:27', '', '2021-01-13 23:50:35', NULL, '2022-07-08 01:26:27', 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$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2023-09-24 18:21:19', '', '2021-01-21 02:13:53', NULL, '2023-09-24 18:21:19', b'0', 1); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/ServiceErrorCodeRange.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/ServiceErrorCodeRange.java index be22815eb..94dd67c9e 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/ServiceErrorCodeRange.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/exception/enums/ServiceErrorCodeRange.java @@ -35,9 +35,12 @@ public class ServiceErrorCodeRange { // 模块 member 错误码区间 [1-004-000-000 ~ 1-005-000-000) // 模块 mp 错误码区间 [1-006-000-000 ~ 1-007-000-000) // 模块 pay 错误码区间 [1-007-000-000 ~ 1-008-000-000) - // 模块 product 错误码区间 [1-008-000-000 ~ 1-009-000-000) // 模块 bpm 错误码区间 [1-009-000-000 ~ 1-010-000-000) + + // 模块 product 错误码区间 [1-008-000-000 ~ 1-009-000-000) // 模块 trade 错误码区间 [1-011-000-000 ~ 1-012-000-000) // 模块 promotion 错误码区间 [1-013-000-000 ~ 1-014-000-000) + // 模块 crm 错误码区间 [1-020-000-000 ~ 1-021-000-000) + } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Telephone.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Telephone.java new file mode 100644 index 000000000..910601fd0 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/Telephone.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.common.validation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.*; + +@Target({ + ElementType.METHOD, + ElementType.FIELD, + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.PARAMETER, + ElementType.TYPE_USE +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = TelephoneValidator.class +) +public @interface Telephone { + + String message() default "电话格式不正确"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/TelephoneValidator.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/TelephoneValidator.java new file mode 100644 index 000000000..d214cfeef --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/validation/TelephoneValidator.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.framework.common.validation; + +import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.PhoneUtil; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class TelephoneValidator implements ConstraintValidator { + + @Override + public void initialize(Telephone annotation) { + } + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + // 如果手机号为空,默认不校验,即校验通过 + if (CharSequenceUtil.isEmpty(value)) { + return true; + } + // 校验手机 + return PhoneUtil.isTel(value) || PhoneUtil.isPhone(value); + } + +} diff --git a/yudao-module-crm/pom.xml b/yudao-module-crm/pom.xml new file mode 100644 index 000000000..2a7b748c3 --- /dev/null +++ b/yudao-module-crm/pom.xml @@ -0,0 +1,25 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + + yudao-module-crm-api + yudao-module-crm-biz + + 4.0.0 + yudao-module-crm + pom + + ${project.artifactId} + + + crm 包下,客户关系管理(Customer Relationship Management)。 + 例如说:客户、联系人、商机、合同、回款等等 + + + diff --git a/yudao-module-crm/yudao-module-crm-api/pom.xml b/yudao-module-crm/yudao-module-crm-api/pom.xml new file mode 100644 index 000000000..94e129626 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/pom.xml @@ -0,0 +1,33 @@ + + + + cn.iocoder.boot + yudao-module-crm + ${revision} + + 4.0.0 + yudao-module-crm-api + jar + + ${project.artifactId} + + crm 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/package-info.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/package-info.java new file mode 100644 index 000000000..c38bde7f5 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/api/package-info.java @@ -0,0 +1,4 @@ +/** + * crm API 包,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.crm.api; diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java new file mode 100644 index 000000000..0e412ee9b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.crm.enums; + +/** + * CRM 字典类型的枚举类 + * + * @author 芋道源码 + */ +public interface DictTypeConstants { + + // ========== CRM 模块 ========== + String CRM_CUSTOMER_INDUSTRY = "crm_customer_industry"; // CRM 客户所属行业 + String CRM_CUSTOMER_LEVEL = "crm_customer_level"; // CRM 客户等级 + String CRM_CUSTOMER_SOURCE = "crm_customer_source"; // CRM 客户来源 + +} diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java new file mode 100644 index 000000000..0977faa70 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.crm.enums; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * CRM 错误码枚举类 + *

+ * crm 系统,使用 1-020-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== 合同管理 1-020-000-000 ========== + ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在"); + + // ========== 线索管理 1-020-001-000 ========== + ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); + + // ========== 商机管理 1-020-002-000 ========== + ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); + + // TODO @lilleo:商机状态、商机类型,都单独错误码段 + + ErrorCode BUSINESS_STATUS_TYPE_NOT_EXISTS = new ErrorCode(1_020_002_001, "商机状态类型不存在"); + ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_002_002, "商机状态不存在"); + + // ========== 联系人管理 1-020-003-000 ========== + ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); + + // TODO @liuhongfeng:错误码分段; + ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_030_000_001, "回款管理不存在"); + + ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_040_000_001, "回款计划不存在"); + + // ========== 客户管理 1_020_006_000 ========== + ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_006_000, "客户不存在"); + + // TODO @puhui999:权限管理??? + // ========== 客户管理 1_020_007_000 ========== + ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); + ErrorCode CRM_PERMISSION_DENIED = new ErrorCode(1_020_007_001, "{}操作失败,原因:没有权限"); + ErrorCode CRM_PERMISSION_MODEL_NOT_EXISTS = new ErrorCode(1_020_007_002, "{}不存在"); + ErrorCode CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_NOT_EXISTS = new ErrorCode(1_020_007_003, "{}操作失败,原因:负责人不存在"); + ErrorCode CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS = new ErrorCode(1_020_007_004, "{}操作失败,原因:转移对象已经是该负责人"); + +} diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/PermissionTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/PermissionTypeEnum.java new file mode 100644 index 000000000..1f94ce3fd --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/PermissionTypeEnum.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.crm.enums.common; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum PermissionTypeEnum implements IntArrayValuable { + + READONLY(1, "只读"), + READ_AND_WRITE(2, "读写"); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PermissionTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/TransferTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/TransferTypeEnum.java new file mode 100644 index 000000000..7a4396265 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/TransferTypeEnum.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.crm.enums.common; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +// TODO @puhui999:这个可以不用哈 +/** + * Crm 负责人转移后原负责人的处理方式 + * + * @author HUIHUI + */ +@Getter +@AllArgsConstructor +public enum TransferTypeEnum implements IntArrayValuable { + + REMOVE(1, "移除"), + TEAM(2, "转为团队成员"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TransferTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLevelEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLevelEnum.java new file mode 100644 index 000000000..f58028314 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLevelEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.crm.enums.customer; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * CRM 客户等级 + * + * @author Wanwan + */ +@Getter +@AllArgsConstructor +public enum CrmCustomerLevelEnum implements IntArrayValuable { + + IMPORTANT(1, "A(重点客户)"), + GENERAL(2, "B(普通客户)"), + LOW_PRIORITY(3, "C(非优先客户)"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLevelEnum::getStatus).toArray(); + + // TODO @wanwan:这里的 status 字段,可以考虑改成 level + /** + * 状态 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/pom.xml b/yudao-module-crm/yudao-module-crm-biz/pom.xml new file mode 100644 index 000000000..5bedf5eac --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/pom.xml @@ -0,0 +1,66 @@ + + + + cn.iocoder.boot + yudao-module-crm + ${revision} + + 4.0.0 + yudao-module-crm-biz + + ${project.artifactId} + + crm 包下,客户关系管理(Customer Relationship Management)。 + 例如说:客户、联系人、商机、合同、回款等等 + + + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-crm-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/package-info.java new file mode 100644 index 000000000..5c4e2493e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/package-info.java @@ -0,0 +1,4 @@ +/** + * crm API 实现类,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.crm.api; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http new file mode 100644 index 000000000..631824e31 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.http @@ -0,0 +1,11 @@ +PUT {{baseUrl}}/crm/business/transfer +Content-Type: application/json +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + +{ + "id": 1, + "ownerUserId": 2, + "transferType": 2, + "permissionType": 2 +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java new file mode 100644 index 000000000..efff25372 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*; +import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - 商机") +@RestController +@RequestMapping("/crm/business") +@Validated +public class CrmBusinessController { + + @Resource + private CrmBusinessService businessService; + + @PostMapping("/create") + @Operation(summary = "创建商机") + @PreAuthorize("@ss.hasPermission('crm:business:create')") + public CommonResult createBusiness(@Valid @RequestBody CrmBusinessCreateReqVO createReqVO) { + return success(businessService.createBusiness(createReqVO, getLoginUserId())); + } + + @PutMapping("/update") + @Operation(summary = "更新商机") + @PreAuthorize("@ss.hasPermission('crm:business:update')") + public CommonResult updateBusiness(@Valid @RequestBody CrmBusinessUpdateReqVO updateReqVO) { + businessService.updateBusiness(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除商机") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:business:delete')") + public CommonResult deleteBusiness(@RequestParam("id") Long id) { + businessService.deleteBusiness(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得商机") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:business:query')") + public CommonResult getBusiness(@RequestParam("id") Long id) { + CrmBusinessDO business = businessService.getBusiness(id); + return success(CrmBusinessConvert.INSTANCE.convert(business)); + } + + @GetMapping("/page") + @Operation(summary = "获得商机分页") + @PreAuthorize("@ss.hasPermission('crm:business:query')") + public CommonResult> getBusinessPage(@Valid CrmBusinessPageReqVO pageVO) { + PageResult pageResult = businessService.getBusinessPage(pageVO); + + return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出商机 Excel") + @PreAuthorize("@ss.hasPermission('crm:business:export')") + @OperateLog(type = EXPORT) + public void exportBusinessExcel(@Valid CrmBusinessExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = businessService.getBusinessList(exportReqVO); + // 导出 Excel + List datas = CrmBusinessConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessExcelVO.class, datas); + } + + @PutMapping("/transfer") + @Operation(summary = "商机转移") + @PreAuthorize("@ss.hasPermission('crm:business:update')") + public CommonResult transfer(@Valid @RequestBody CrmTransferBusinessReqVO reqVO) { + businessService.transferBusiness(reqVO, getLoginUserId()); + return success(true); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/package-info.java new file mode 100644 index 000000000..07dec89b1 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/package-info.java @@ -0,0 +1,4 @@ +/** + * 商机(销售机会) + */ +package cn.iocoder.yudao.module.crm.controller.admin.business; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessBaseVO.java new file mode 100644 index 000000000..9bcffb117 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessBaseVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 商机 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class CrmBusinessBaseVO { + + @Schema(description = "商机名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotNull(message = "商机名称不能为空") + private String name; + + @Schema(description = "商机状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25714") + @NotNull(message = "商机状态类型不能为空") + private Long statusTypeId; + + @Schema(description = "商机状态编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") + @NotNull(message = "商机状态不能为空") + private Long statusId; + + @Schema(description = "下次联系时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime contactNextTime; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10299") + @NotNull(message = "客户不能为空") + private Long customerId; + + @Schema(description = "预计成交日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime dealTime; + + @Schema(description = "商机金额", example = "12371") + private Integer price; + + // TODO @ljileo:折扣使用 Integer 类型,存储时,默认 * 100;展示的时候,前端需要 / 100;避免精度丢失问题 + @Schema(description = "整单折扣") + private Integer discountPercent; + + @Schema(description = "产品总金额", example = "12025") + private BigDecimal productPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessCreateReqVO.java new file mode 100644 index 000000000..f743c8469 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessCreateReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.vo; + +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 CrmBusinessCreateReqVO extends CrmBusinessBaseVO { + + // TODO @ljileo:新建的时候,应该可以传递添加的产品; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExcelVO.java new file mode 100644 index 000000000..e7e3ef987 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExcelVO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Set; + +/** + * 商机 Excel VO + * + * @author ljlleo + */ +@Data +public class CrmBusinessExcelVO { + + @ExcelProperty("主键") + private Long id; + + @ExcelProperty("商机名称") + private String name; + + @ExcelProperty("商机状态类型编号") + private Long statusTypeId; + + @ExcelProperty("商机状态编号") + private Long statusId; + + @ExcelProperty("下次联系时间") + private LocalDateTime contactNextTime; + + @ExcelProperty("客户编号") + private Long customerId; + + @ExcelProperty("预计成交日期") + private LocalDateTime dealTime; + + @ExcelProperty("商机金额") + private BigDecimal price; + + @ExcelProperty("整单折扣") + private BigDecimal discountPercent; + + @ExcelProperty("产品总金额") + private BigDecimal productPrice; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("负责人的用户编号") + private Long ownerUserId; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @ExcelProperty("只读权限的用户编号数组") + private Set roUserIds; + + @ExcelProperty("读写权限的用户编号数组") + private Set rwUserIds; + + @ExcelProperty("1赢单2输单3无效") + private Integer endStatus; + + @ExcelProperty("结束时的备注") + private String endRemark; + + @ExcelProperty("最后跟进时间") + private LocalDateTime contactLastTime; + + @ExcelProperty("跟进状态") + private Integer followUpStatus; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExportReqVO.java new file mode 100644 index 000000000..a44283112 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessExportReqVO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 商机 Excel 导出 Request VO,参数和 CrmBusinessPageReqVO 是一致的") +@Data +public class CrmBusinessExportReqVO { + + @Schema(description = "商机名称", example = "李四") + private String name; + + @Schema(description = "商机状态类型编号", example = "25714") + private Long statusTypeId; + + @Schema(description = "商机状态编号", example = "30320") + private Long statusId; + + @Schema(description = "下次联系时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] contactNextTime; + + @Schema(description = "客户编号", example = "10299") + private Long customerId; + + @Schema(description = "预计成交日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] dealTime; + + @Schema(description = "商机金额", example = "12371") + private BigDecimal price; + + @Schema(description = "整单折扣") + private BigDecimal discountPercent; + + @Schema(description = "产品总金额", example = "12025") + private BigDecimal productPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "负责人的用户编号", example = "25562") + private Long ownerUserId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "只读权限的用户编号数组") + private String roUserIds; + + @Schema(description = "读写权限的用户编号数组") + private String rwUserIds; + + @Schema(description = "1赢单2输单3无效", example = "1") + private Integer endStatus; + + @Schema(description = "结束时的备注", example = "你说的对") + private String endRemark; + + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] contactLastTime; + + @Schema(description = "跟进状态", example = "1") + private Integer followUpStatus; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessPageReqVO.java new file mode 100644 index 000000000..c8368cce7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessPageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.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 = "管理后台 - 商机分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessPageReqVO extends PageParam { + + @Schema(description = "商机名称", example = "李四") + private String name; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessRespVO.java new file mode 100644 index 000000000..672f99ec3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 商机 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessRespVO extends CrmBusinessBaseVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessUpdateReqVO.java new file mode 100644 index 000000000..f137d4c5b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmBusinessUpdateReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 商机更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessUpdateReqVO extends CrmBusinessBaseVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") + @NotNull(message = "主键不能为空") + private Long id; + + // TODO @ljileo:修改的时候,应该可以传递添加的产品; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmTransferBusinessReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmTransferBusinessReqVO.java new file mode 100644 index 000000000..075cfb764 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/CrmTransferBusinessReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.crm.controller.admin.business.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum; +import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 商机转移 Request VO") +@Data +public class CrmTransferBusinessReqVO { + + @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "联系人编号不能为空") + private Long id; + + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "新负责人的用户编号不能为空") + private Long ownerUserId; + + @Schema(description = "原负责人移除方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @InEnum(TransferTypeEnum.class) + @NotNull(message = "原负责人移除方式不能为空") + private Integer transferType; + + @Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @InEnum(PermissionTypeEnum.class) + @NotNull(message = "权限类型不能为空") + private Integer permissionType; + + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/CrmBusinessStatusController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/CrmBusinessStatusController.java new file mode 100644 index 000000000..275285098 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/CrmBusinessStatusController.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatus; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.*; +import cn.iocoder.yudao.module.crm.convert.businessstatus.CrmBusinessStatusConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO; +import cn.iocoder.yudao.module.crm.service.businessstatus.CrmBusinessStatusService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +// TODO @lilleo:这个模块,可以挪到 business 下;这样我打开 business 包下,就知道,噢~原来里面有 business 商机、有 type 状态类型、status 具体状态; +@Tag(name = "管理后台 - 商机状态") +@RestController +@RequestMapping("/crm/business-status") +@Validated +public class CrmBusinessStatusController { + + @Resource + private CrmBusinessStatusService businessStatusService; + + @PostMapping("/create") + @Operation(summary = "创建商机状态") + @PreAuthorize("@ss.hasPermission('crm:business-status:create')") + public CommonResult createBusinessStatus(@Valid @RequestBody CrmBusinessStatusCreateReqVO createReqVO) { + return success(businessStatusService.createBusinessStatus(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新商机状态") + @PreAuthorize("@ss.hasPermission('crm:business-status:update')") + public CommonResult updateBusinessStatus(@Valid @RequestBody CrmBusinessStatusUpdateReqVO updateReqVO) { + businessStatusService.updateBusinessStatus(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除商机状态") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:business-status:delete')") + public CommonResult deleteBusinessStatus(@RequestParam("id") Long id) { + businessStatusService.deleteBusinessStatus(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得商机状态") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:business-status:query')") + public CommonResult getBusinessStatus(@RequestParam("id") Long id) { + CrmBusinessStatusDO businessStatus = businessStatusService.getBusinessStatus(id); + return success(CrmBusinessStatusConvert.INSTANCE.convert(businessStatus)); + } + + // TODO @lilleo:这个接口,暂时用不到,可以考虑先删除掉 + @GetMapping("/list") + @Operation(summary = "获得商机状态列表") + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") + @PreAuthorize("@ss.hasPermission('crm:business-status:query')") + public CommonResult> getBusinessStatusList(@RequestParam("ids") Collection ids) { + List list = businessStatusService.getBusinessStatusList(ids); + return success(CrmBusinessStatusConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得商机状态分页") + @PreAuthorize("@ss.hasPermission('crm:business-status:query')") + public CommonResult> getBusinessStatusPage(@Valid CrmBusinessStatusPageReqVO pageVO) { + PageResult pageResult = businessStatusService.getBusinessStatusPage(pageVO); + return success(CrmBusinessStatusConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出商机状态 Excel") + @PreAuthorize("@ss.hasPermission('crm:business-status:export')") + @OperateLog(type = EXPORT) + public void exportBusinessStatusExcel(@Valid CrmBusinessStatusExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = businessStatusService.getBusinessStatusList(exportReqVO); + // 导出 Excel + List datas = CrmBusinessStatusConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "商机状态.xls", "数据", CrmBusinessStatusExcelVO.class, datas); + } + + // TODO 芋艿:后续再看看 + @GetMapping("/get-simple-list") + @Operation(summary = "获得商机状态列表") + @PreAuthorize("@ss.hasPermission('crm:business-status:query')") + public CommonResult> getBusinessStatusListByTypeId(@RequestParam("typeId") Integer typeId) { + List list = businessStatusService.getBusinessStatusListByTypeId(typeId); + return success(CrmBusinessStatusConvert.INSTANCE.convertList(list)); + } + + // TODO 芋艿:后续再看看 + @GetMapping("/get-all-list") + @Operation(summary = "获得商机状态列表") + @PreAuthorize("@ss.hasPermission('crm:business-status:query')") + public CommonResult> getBusinessStatusList() { + List list = businessStatusService.getBusinessStatusList(); + return success(CrmBusinessStatusConvert.INSTANCE.convertList(list)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusBaseVO.java new file mode 100644 index 000000000..401e35fbe --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusBaseVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 商机状态 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class CrmBusinessStatusBaseVO { + + // TODO @lilleo:example 要写下 + + @Schema(description = "状态类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22882") + @NotNull(message = "状态类型编号不能为空") + private Long typeId; + + @Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotNull(message = "状态名不能为空") + private String name; + + // TODO @lilleo:percent 应该是 Integer; + @Schema(description = "赢单率") + private String percent; + + // TODO @lilleo:这个是不是不用前端新增和修改的时候传递,交给顺序计算出来,存储起来就好了; + @Schema(description = "排序") + private Integer sort; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusCreateReqVO.java new file mode 100644 index 000000000..04e999474 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - 商机状态创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessStatusCreateReqVO extends CrmBusinessStatusBaseVO { + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExcelVO.java new file mode 100644 index 000000000..78da092f7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExcelVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +// TODO @lilleo:这个暂时不需要;嘿嘿~不是每个模块都需要导出哈 +/** + * 商机状态 Excel VO + * + * @author ljlleo + */ +@Data +public class CrmBusinessStatusExcelVO { + + @ExcelProperty("主键") + private Long id; + + @ExcelProperty("状态类型编号") + private Long typeId; + + @ExcelProperty("状态名") + private String name; + + @ExcelProperty("赢单率") + private String percent; + + @ExcelProperty("排序") + private Integer sort; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExportReqVO.java new file mode 100644 index 000000000..7f7fba6c7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusExportReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +// TODO @lilleo:这个暂时不需要;嘿嘿~不是每个模块都需要导出哈 +@Schema(description = "管理后台 - 商机状态 Excel 导出 Request VO,参数和 CrmBusinessStatusPageReqVO 是一致的") +@Data +public class CrmBusinessStatusExportReqVO { + + @Schema(description = "状态类型编号", example = "22882") + private Long typeId; + + @Schema(description = "状态名", example = "李四") + private String name; + + @Schema(description = "赢单率") + private String percent; + + @Schema(description = "排序") + private Integer sort; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusPageReqVO.java new file mode 100644 index 000000000..af03512af --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusPageReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.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 = "管理后台 - 商机状态分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessStatusPageReqVO extends PageParam { + + @Schema(description = "状态类型编号", example = "22882") + private Long typeId; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusRespVO.java new file mode 100644 index 000000000..54f675272 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusRespVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +@Schema(description = "管理后台 - 商机状态 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessStatusRespVO extends CrmBusinessStatusBaseVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6802") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusUpdateReqVO.java new file mode 100644 index 000000000..429902164 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatus/vo/CrmBusinessStatusUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 商机状态更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessStatusUpdateReqVO extends CrmBusinessStatusBaseVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6802") + @NotNull(message = "编号不能为空") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/CrmBusinessStatusTypeController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/CrmBusinessStatusTypeController.java new file mode 100644 index 000000000..25ba7448f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/CrmBusinessStatusTypeController.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.*; +import cn.iocoder.yudao.module.crm.convert.businessstatustype.CrmBusinessStatusTypeConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO; +import cn.iocoder.yudao.module.crm.service.businessstatustype.CrmBusinessStatusTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +// TODO @lilleo:这个模块,可以挪到 business 下;这样我打开 business 包下,就知道,噢~原来里面有 business 商机、有 type 状态类型、status 具体状态; +@Tag(name = "管理后台 - 商机状态类型") +@RestController +@RequestMapping("/crm/business-status-type") +@Validated +public class CrmBusinessStatusTypeController { + + @Resource + private CrmBusinessStatusTypeService businessStatusTypeService; + + @PostMapping("/create") + @Operation(summary = "创建商机状态类型") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:create')") + public CommonResult createBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeCreateReqVO createReqVO) { + return success(businessStatusTypeService.createBusinessStatusType(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新商机状态类型") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:update')") + public CommonResult updateBusinessStatusType(@Valid @RequestBody CrmBusinessStatusTypeUpdateReqVO updateReqVO) { + businessStatusTypeService.updateBusinessStatusType(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除商机状态类型") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:business-status-type:delete')") + public CommonResult deleteBusinessStatusType(@RequestParam("id") Long id) { + businessStatusTypeService.deleteBusinessStatusType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得商机状态类型") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") + public CommonResult getBusinessStatusType(@RequestParam("id") Long id) { + CrmBusinessStatusTypeDO businessStatusType = businessStatusTypeService.getBusinessStatusType(id); + return success(CrmBusinessStatusTypeConvert.INSTANCE.convert(businessStatusType)); + } + + // TODO @lilleo:这个接口,暂时用不到,可以考虑先删除掉 + @GetMapping("/list") + @Operation(summary = "获得商机状态类型列表") + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") + public CommonResult> getBusinessStatusTypeList(@RequestParam("ids") Collection ids) { + List list = businessStatusTypeService.getBusinessStatusTypeList(ids); + return success(CrmBusinessStatusTypeConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得商机状态类型分页") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") + public CommonResult> getBusinessStatusTypePage(@Valid CrmBusinessStatusTypePageReqVO pageVO) { + PageResult pageResult = businessStatusTypeService.getBusinessStatusTypePage(pageVO); + return success(CrmBusinessStatusTypeConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出商机状态类型 Excel") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:export')") + @OperateLog(type = EXPORT) + public void exportBusinessStatusTypeExcel(@Valid CrmBusinessStatusTypeExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = businessStatusTypeService.getBusinessStatusTypeList(exportReqVO); + // 导出 Excel + List datas = CrmBusinessStatusTypeConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "商机状态类型.xls", "数据", CrmBusinessStatusTypeExcelVO.class, datas); + } + + @GetMapping("/get-simple-list") + @Operation(summary = "获得商机状态类型列表") + @PreAuthorize("@ss.hasPermission('crm:business-status-type:query')") + public CommonResult> getBusinessStatusTypeList() { + List list = businessStatusTypeService.getBusinessStatusTypeListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(CrmBusinessStatusTypeConvert.INSTANCE.convertList(list)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeBaseVO.java new file mode 100644 index 000000000..c472a3471 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeBaseVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * 商机状态类型 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class CrmBusinessStatusTypeBaseVO { + + @Schema(description = "状态类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotNull(message = "状态类型名不能为空") + private String name; + + @Schema(description = "使用的部门编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "使用的部门编号不能为空") + private String deptIds; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + private Boolean status; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeCreateReqVO.java new file mode 100644 index 000000000..5000e25ee --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeCreateReqVO.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +// TODO 状态类型和状态添加,是在一个请求里,所以需要把 CrmBusinessStatusCreateReqVO 融合进来; +@Schema(description = "管理后台 - 商机状态类型创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessStatusTypeCreateReqVO extends CrmBusinessStatusTypeBaseVO { + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExcelVO.java new file mode 100644 index 000000000..cc6ed8502 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExcelVO.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +// TODO @lilleo:这个暂时不需要;嘿嘿~不是每个模块都需要导出哈 +/** + * 商机状态类型 Excel VO + * + * @author ljlleo + */ +@Data +public class CrmBusinessStatusTypeExcelVO { + + @ExcelProperty("主键") + private Long id; + + @ExcelProperty("状态类型名") + private String name; + + @ExcelProperty("使用的部门编号") + private String deptIds; + + @ExcelProperty("开启状态") + private Boolean status; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExportReqVO.java new file mode 100644 index 000000000..1345565be --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeExportReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +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; + +// TODO @lilleo:这个暂时不需要;嘿嘿~不是每个模块都需要导出哈 +@Schema(description = "管理后台 - 商机状态类型 Excel 导出 Request VO,参数和 CrmBusinessStatusTypePageReqVO 是一致的") +@Data +public class CrmBusinessStatusTypeExportReqVO { + + @Schema(description = "状态类型名", example = "芋艿") + private String name; + + @Schema(description = "使用的部门编号") + private String deptIds; + + @Schema(description = "开启状态", example = "1") + private Boolean status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypePageReqVO.java new file mode 100644 index 000000000..4b15210ac --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypePageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.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 = "管理后台 - 商机状态类型分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessStatusTypePageReqVO extends PageParam { + + @Schema(description = "状态类型名", example = "芋艿") + private String name; + + @Schema(description = "开启状态", example = "1") + private Boolean status; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeRespVO.java new file mode 100644 index 000000000..a4e21c58e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 商机状态类型 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessStatusTypeRespVO extends CrmBusinessStatusTypeBaseVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "24019") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeUpdateReqVO.java new file mode 100644 index 000000000..0eb93224c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/businessstatustype/vo/CrmBusinessStatusTypeUpdateReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +// TODO 状态类型和状态添加,是在一个请求里,所以需要把 CrmBusinessStatusUpdateReqVO 融合进来; +@Schema(description = "管理后台 - 商机状态类型更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmBusinessStatusTypeUpdateReqVO extends CrmBusinessStatusTypeBaseVO { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "24019") + @NotNull(message = "主键不能为空") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java new file mode 100644 index 000000000..8892a8e71 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; +import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - 线索") +@RestController +@RequestMapping("/crm/clue") +@Validated +public class CrmClueController { + + @Resource + private CrmClueService clueService; + + @PostMapping("/create") + @Operation(summary = "创建线索") + @PreAuthorize("@ss.hasPermission('crm:clue:create')") + public CommonResult createClue(@Valid @RequestBody CrmClueCreateReqVO createReqVO) { + return success(clueService.createClue(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新线索") + @PreAuthorize("@ss.hasPermission('crm:clue:update')") + public CommonResult updateClue(@Valid @RequestBody CrmClueUpdateReqVO updateReqVO) { + clueService.updateClue(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除线索") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:clue:delete')") + public CommonResult deleteClue(@RequestParam("id") Long id) { + clueService.deleteClue(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得线索") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:clue:query')") + public CommonResult getClue(@RequestParam("id") Long id) { + CrmClueDO clue = clueService.getClue(id); + return success(CrmClueConvert.INSTANCE.convert(clue)); + } + + @GetMapping("/page") + @Operation(summary = "获得线索分页") + @PreAuthorize("@ss.hasPermission('crm:clue:query')") + public CommonResult> getCluePage(@Valid CrmCluePageReqVO pageVO) { + PageResult pageResult = clueService.getCluePage(pageVO); + return success(CrmClueConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出线索 Excel") + @PreAuthorize("@ss.hasPermission('crm:clue:export')") + @OperateLog(type = EXPORT) + public void exportClueExcel(@Valid CrmClueExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = clueService.getClueList(exportReqVO); + // 导出 Excel + List datas = CrmClueConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "线索.xls", "数据", CrmClueExcelVO.class, datas); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/package-info.java new file mode 100644 index 000000000..0dc110844 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/package-info.java @@ -0,0 +1,4 @@ +/** + * 线索 + */ +package cn.iocoder.yudao.module.crm.controller.admin.clue; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueBaseVO.java new file mode 100644 index 000000000..f8ca48444 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueBaseVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.framework.common.validation.Telephone; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 线索 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class CrmClueBaseVO { + + @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx") + @NotEmpty(message = "线索名称不能为空") + private String name; + + @Schema(description = "客户 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "520") + @NotNull(message = "客户不能为空") + private Long customerId; + + @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime contactNextTime; + + @Schema(description = "电话", example = "18000000000") + @Telephone + private String telephone; + + @Schema(description = "手机号", example = "18000000000") + @Mobile + private String mobile; + + @Schema(description = "地址", example = "北京市海淀区") + private String address; + + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime contactLastTime; + + @Schema(description = "备注", example = "随便") + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueCreateReqVO.java new file mode 100644 index 000000000..0d43e15a6 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - 线索创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmClueCreateReqVO extends CrmClueBaseVO { + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExcelVO.java new file mode 100644 index 000000000..d6457bd56 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExcelVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; + +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; + +import com.alibaba.excel.annotation.ExcelProperty; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +/** + * 线索 Excel VO + * + * @author Wanwan + */ +@Data +public class CrmClueExcelVO { + + @ExcelProperty("编号") + private Long id; + + @ExcelProperty(value = "转化状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) + private Boolean transformStatus; + + @ExcelProperty(value = "跟进状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) + private Boolean followUpStatus; + + @ExcelProperty("线索名称") + private String name; + + // TODO 这里需要导出成客户名称 + @ExcelProperty("客户id") + private Long customerId; + + @ExcelProperty("下次联系时间") + private LocalDateTime contactNextTime; + + @ExcelProperty("电话") + private String telephone; + + @ExcelProperty("手机号") + private String mobile; + + @ExcelProperty("地址") + private String address; + + @ExcelProperty("负责人的用户编号") + private Long ownerUserId; + + @ExcelProperty("最后跟进时间") + private LocalDateTime contactLastTime; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExportReqVO.java new file mode 100644 index 000000000..fe061b365 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExportReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.time.LocalDateTime; +import org.springframework.format.annotation.DateTimeFormat; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 线索 Excel 导出 Request VO,参数和 CrmCluePageReqVO 是一致的") +@Data +public class CrmClueExportReqVO { + + @Schema(description = "转化状态", example = "true") + private Boolean transformStatus; + + @Schema(description = "跟进状态", example = "true") + private Boolean followUpStatus; + + @Schema(description = "线索名称", example = "线索xxx") + private String name; + + @Schema(description = "客户id", example = "520") + private Long customerId; + + @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] contactNextTime; + + @Schema(description = "电话", example = "18000000000") + private String telephone; + + @Schema(description = "手机号", example = "18000000000") + private String mobile; + + @Schema(description = "地址", example = "北京市海淀区") + private String address; + + @Schema(description = "负责人的用户编号", example = "27199") + private Long ownerUserId; + + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] contactLastTime; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java new file mode 100644 index 000000000..4d28ebc73 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue.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 = "管理后台 - 线索分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmCluePageReqVO extends PageParam { + + @Schema(description = "线索名称", example = "线索xxx") + private String name; + + @Schema(description = "电话", example = "18000000000") + private String telephone; + + @Schema(description = "手机号", example = "18000000000") + private String mobile; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java new file mode 100644 index 000000000..6d2d30334 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 线索 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmClueRespVO extends CrmClueBaseVO { + + @Schema(description = "编号,主键自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "10969") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + @Schema(description = "转化状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean transformStatus; + + @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean followUpStatus; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueUpdateReqVO.java new file mode 100644 index 000000000..4526fbd2b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 线索更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmClueUpdateReqVO extends CrmClueBaseVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10969") + @NotNull(message = "编号不能为空") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/ContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/ContactController.java new file mode 100644 index 000000000..cda6b29b9 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/ContactController.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; +import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO; +import cn.iocoder.yudao.module.crm.service.contact.ContactService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - CRM 联系人") +@RestController +@RequestMapping("/crm/contact") +@Validated +public class ContactController { + + @Resource + private ContactService contactService; + + @PostMapping("/create") + @Operation(summary = "创建crm联系人") + @PreAuthorize("@ss.hasPermission('crm:contact:create')") + public CommonResult createContact(@Valid @RequestBody ContactCreateReqVO createReqVO) { + return success(contactService.createContact(createReqVO, getLoginUserId())); + } + + @PutMapping("/update") + @Operation(summary = "更新crm联系人") + @PreAuthorize("@ss.hasPermission('crm:contact:update')") + public CommonResult updateContact(@Valid @RequestBody ContactUpdateReqVO updateReqVO) { + contactService.updateContact(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除crm联系人") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:contact:delete')") + public CommonResult deleteContact(@RequestParam("id") Long id) { + contactService.deleteContact(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得crm联系人") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:contact:query')") + public CommonResult getContact(@RequestParam("id") Long id) { + ContactDO contact = contactService.getContact(id); + return success(ContactConvert.INSTANCE.convert(contact)); + } + + @GetMapping("/list") + @Operation(summary = "获得crm联系人列表") + @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048") + @PreAuthorize("@ss.hasPermission('crm:contact:query')") + public CommonResult> getContactList(@RequestParam("ids") Collection ids) { + List list = contactService.getContactList(ids); + return success(ContactConvert.INSTANCE.convertList(list)); + } + + @GetMapping("/page") + @Operation(summary = "获得crm联系人分页") + @PreAuthorize("@ss.hasPermission('crm:contact:query')") + public CommonResult> getContactPage(@Valid ContactPageReqVO pageVO) { + PageResult pageResult = contactService.getContactPage(pageVO); + return success(ContactConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出crm联系人 Excel") + @PreAuthorize("@ss.hasPermission('crm:contact:export')") + @OperateLog(type = EXPORT) + public void exportContactExcel(@Valid ContactExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = contactService.getContactList(exportReqVO); + // 导出 Excel + List datas = ContactConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "crm联系人.xls", "数据", ContactExcelVO.class, datas); + } + + @PutMapping("/transfer") + @Operation(summary = "联系人转移") + @PreAuthorize("@ss.hasPermission('crm:contact:update')") + public CommonResult transfer(@Valid @RequestBody CrmTransferContactReqVO reqVO) { + contactService.transferContact(reqVO, getLoginUserId()); + return success(true); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactBaseVO.java new file mode 100644 index 000000000..0f9da5c06 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactBaseVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * crm联系人 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class ContactBaseVO { + + // TODO @zyna:部分字段,缺少 example,需要补充; + + @Schema(description = "联系人名称", example = "张三") + @NotNull(message = "姓名不能为空") + private String name; + + @Schema(description = "下次联系时间") + private LocalDateTime nextTime; + + // TODO @zyna:缺少 validator 的校验 + @Schema(description = "手机号") + private String mobile; + + // TODO @zyna:缺少 validator 的校验 + @Schema(description = "电话") + private String telephone; + + // TODO @zyna:缺少 validator 的校验 + @Schema(description = "电子邮箱") + private String email; + + @Schema(description = "职务") + private String post; + + // TODO @zyna:非空校验 + @Schema(description = "客户编号", example = "10795") + private Long customerId; + + @Schema(description = "地址") + private String address; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + // TODO @zyna:这个新建的时候,应该不会传递;而是后端默认设置自己为负责人; + @Schema(description = "负责人用户编号", example = "7648") + private Long ownerUserId; + + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime lastTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactCreateReqVO.java new file mode 100644 index 000000000..5eccfea74 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - CRM 联系人创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContactCreateReqVO extends ContactBaseVO { + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExcelVO.java new file mode 100644 index 000000000..3ac5f3765 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExcelVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; + +import com.alibaba.excel.annotation.ExcelProperty; + +/** + * crm联系人 Excel VO + * + * @author 芋道源码 + */ +@Data +public class ContactExcelVO { + + @ExcelProperty("主键") + private Long id; + + @ExcelProperty("联系人名称") + private String name; + + @ExcelProperty("下次联系时间") + private LocalDateTime nextTime; + + @ExcelProperty("手机号") + private String mobile; + + @ExcelProperty("电话") + private String telephone; + + @ExcelProperty("电子邮箱") + private String email; + + @ExcelProperty("职务") + private String post; + + @ExcelProperty("客户编号") + private Long customerId; + + @ExcelProperty("地址") + private String address; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("负责人用户编号") + private Long ownerUserId; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @ExcelProperty("最后跟进时间") + private LocalDateTime lastTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExportReqVO.java new file mode 100644 index 000000000..961cebd0c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactExportReqVO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.time.LocalDateTime; +import org.springframework.format.annotation.DateTimeFormat; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - CRM 联系人 Excel 导出 Request VO,参数和 ContactPageReqVO 是一致的") +@Data +public class ContactExportReqVO { + + @Schema(description = "联系人名称", example = "张三") + private String name; + + @Schema(description = "下次联系时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] nextTime; + + @Schema(description = "手机号") + private String mobile; + + @Schema(description = "电话") + private String telephone; + + @Schema(description = "电子邮箱") + private String email; + + @Schema(description = "职务") + private String post; + + @Schema(description = "客户编号", example = "10795") + private Long customerId; + + @Schema(description = "地址") + private String address; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + @Schema(description = "负责人用户编号", example = "7648") + private Long ownerUserId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] lastTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactPageReqVO.java new file mode 100644 index 000000000..64d8a04b9 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactPageReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.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 = "管理后台 - CRM 联系人分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContactPageReqVO extends PageParam { + + // TODO @芋艿:需要查询的字段; + + @Schema(description = "联系人名称", example = "张三") + private String name; + + @Schema(description = "下次联系时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] nextTime; + + @Schema(description = "手机号") + private String mobile; + + @Schema(description = "电话") + private String telephone; + + @Schema(description = "电子邮箱") + private String email; + + @Schema(description = "职务") + private String post; + + @Schema(description = "客户编号", example = "10795") + private Long customerId; + + @Schema(description = "地址") + private String address; + + @Schema(description = "备注", example = "你说的对") + private String remark; + + @Schema(description = "负责人用户编号", example = "7648") + private Long ownerUserId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] lastTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactRespVO.java new file mode 100644 index 000000000..6a02c69d2 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactRespVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 联系人 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContactRespVO extends ContactBaseVO { + + @Schema(description = "主键", example = "23210") + private Long id; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + @Schema(description = "创建人") + private String creator; +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactUpdateReqVO.java new file mode 100644 index 000000000..d2621fa5e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/ContactUpdateReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - CRM 联系人更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContactUpdateReqVO extends ContactBaseVO { + + @Schema(description = "主键", example = "23210") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmTransferContactReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmTransferContactReqVO.java new file mode 100644 index 000000000..1e16d2d20 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmTransferContactReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - CRM 联系人转移 Request VO") +@Data +public class CrmTransferContactReqVO { + + @Schema(description = "联系人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "联系人编号不能为空") + private Long id; + + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "新负责人的用户编号不能为空") + private Long ownerUserId; + + @Schema(description = "原负责人移除方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "原负责人移除方式不能为空") + private Integer transferType; + + @Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "权限类型不能为空") + private Integer permissionType; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/ContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/ContractController.java new file mode 100644 index 000000000..d875b21e3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/ContractController.java @@ -0,0 +1,98 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO; +import cn.iocoder.yudao.module.crm.service.contract.ContractService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - CRM 合同") +@RestController +@RequestMapping("/crm/contract") +@Validated +public class ContractController { + + @Resource + private ContractService contractService; + + @PostMapping("/create") + @Operation(summary = "创建合同") + @PreAuthorize("@ss.hasPermission('crm:contract:create')") + public CommonResult createContract(@Valid @RequestBody ContractCreateReqVO createReqVO) { + return success(contractService.createContract(createReqVO, getLoginUserId())); + } + + @PutMapping("/update") + @Operation(summary = "更新合同") + @PreAuthorize("@ss.hasPermission('crm:contract:update')") + public CommonResult updateContract(@Valid @RequestBody ContractUpdateReqVO updateReqVO) { + contractService.updateContract(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除合同") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:contract:delete')") + public CommonResult deleteContract(@RequestParam("id") Long id) { + contractService.deleteContract(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得合同") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:contract:query')") + public CommonResult getContract(@RequestParam("id") Long id) { + ContractDO contract = contractService.getContract(id); + return success(ContractConvert.INSTANCE.convert(contract)); + } + + @GetMapping("/page") + @Operation(summary = "获得合同分页") + @PreAuthorize("@ss.hasPermission('crm:contract:query')") + public CommonResult> getContractPage(@Valid ContractPageReqVO pageVO) { + PageResult pageResult = contractService.getContractPage(pageVO); + return success(ContractConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出合同 Excel") + @PreAuthorize("@ss.hasPermission('crm:contract:export')") + @OperateLog(type = EXPORT) + public void exportContractExcel(@Valid ContractExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = contractService.getContractList(exportReqVO); + // 导出 Excel + List datas = ContractConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "合同.xls", "数据", ContractExcelVO.class, datas); + } + + @PutMapping("/transfer") + @Operation(summary = "合同转移") + @PreAuthorize("@ss.hasPermission('crm:contract:update')") + public CommonResult transfer(@Valid @RequestBody CrmTransferContractReqVO reqVO) { + contractService.transferContract(reqVO, getLoginUserId()); + return success(true); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractBaseVO.java new file mode 100644 index 000000000..756ee0d1f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractBaseVO.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +// TODO @dhb52:所有类,带下 Crm 前缀,避免和别的模块重复 +/** + * 合同 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class ContractBaseVO { + + // TODO @dhb52:类似 no 字段的 example 要写xia 哈; + + @Schema(description = "合同名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + @NotNull(message = "合同名称不能为空") + private String name; + + // TODO @dhb52:这个必须传递 + @Schema(description = "客户编号", example = "18336") + private Long customerId; + + @Schema(description = "商机编号", example = "10864") + private Long businessId; + + @Schema(description = "工作流编号", example = "1043") + private Long processInstanceId; + + // TODO @dhb52:这个必须传递 + @Schema(description = "下单日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime orderDate; + + // TODO @dhb52:这个必须传递 + @Schema(description = "负责人的用户编号", example = "17144") + private Long ownerUserId; + + // TODO @芋艿:未来应该支持自动生成; + // TODO @dhb52:这个必须传递; + @Schema(description = "合同编号") + private String no; + + @Schema(description = "开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime startTime; + + @Schema(description = "结束时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime endTime; + + @Schema(description = "合同金额", example = "5617") + private Integer price; + + @Schema(description = "整单折扣") + private Integer discountPercent; + + @Schema(description = "产品总金额", example = "19510") + private Integer productPrice; + + @Schema(description = "联系人编号", example = "18546") + private Long contactId; + + @Schema(description = "公司签约人", example = "14036") + private Long signUserId; + + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime contactLastTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + // TODO @dhb52:增加一个 status 字段:具体有哪些值,你来枚举下;主要页面上有个【草稿】【提交审核】的流程,可以看看。然后要对接工作流,这块也可以看看,不确定的地方问我。 + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractCreateReqVO.java new file mode 100644 index 000000000..7793d7737 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - CRM 合同创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContractCreateReqVO extends ContractBaseVO { + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExcelVO.java new file mode 100644 index 000000000..2fb521321 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExcelVO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * CRM 合同 Excel VO + * + * @author dhb52 + */ +@Data +public class ContractExcelVO { + + @ExcelProperty("合同编号") + private Long id; + + @ExcelProperty("合同名称") + private String name; + + @ExcelProperty("客户编号") + private Long customerId; + + @ExcelProperty("商机编号") + private Long businessId; + + @ExcelProperty("工作流编号") + private Long processInstanceId; + + @ExcelProperty("下单日期") + private LocalDateTime orderDate; + + @ExcelProperty("负责人的用户编号") + private Long ownerUserId; + + @ExcelProperty("合同编号") + private String no; + + @ExcelProperty("开始时间") + private LocalDateTime startTime; + + @ExcelProperty("结束时间") + private LocalDateTime endTime; + + @ExcelProperty("合同金额") + private Integer price; + + @ExcelProperty("整单折扣") + private Integer discountPercent; + + @ExcelProperty("产品总金额") + private Integer productPrice; + + @ExcelProperty("联系人编号") + private Long contactId; + + @ExcelProperty("公司签约人") + private Long signUserId; + + @ExcelProperty("最后跟进时间") + private LocalDateTime contactLastTime; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExportReqVO.java new file mode 100644 index 000000000..003e1f57c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractExportReqVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +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 = "管理后台 - CRM 合同 Excel 导出 Request VO,参数和 ContractPageReqVO 是一致的") +@Data +public class ContractExportReqVO { + + @Schema(description = "合同名称", example = "王五") + private String name; + + @Schema(description = "客户编号", example = "18336") + private Long customerId; + + @Schema(description = "商机编号", example = "10864") + private Long businessId; + + @Schema(description = "下单日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] orderDate; + + @Schema(description = "合同编号") + private String no; + + @Schema(description = "整单折扣") + private Integer discountPercent; + + @Schema(description = "产品总金额", example = "19510") + private Integer productPrice; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractPageReqVO.java new file mode 100644 index 000000000..36c7e14be --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractPageReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.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 = "管理后台 - CRM 合同分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContractPageReqVO extends PageParam { + + @Schema(description = "合同名称", example = "王五") + private String name; + + @Schema(description = "客户编号", example = "18336") + private Long customerId; + + @Schema(description = "商机编号", example = "10864") + private Long businessId; + + @Schema(description = "下单日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] orderDate; + + @Schema(description = "合同编号") + private String no; + + @Schema(description = "整单折扣") + private Integer discountPercent; + + @Schema(description = "产品总金额", example = "19510") + private Integer productPrice; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractRespVO.java new file mode 100644 index 000000000..4a22251b0 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 合同 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContractRespVO extends ContractBaseVO { + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractUpdateReqVO.java new file mode 100644 index 000000000..34a9797f4 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/ContractUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - CRM 合同更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ContractUpdateReqVO extends ContractBaseVO { + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "合同编号不能为空") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmTransferContractReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmTransferContractReqVO.java new file mode 100644 index 000000000..a987c9f89 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmTransferContractReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +// TODO @puhui999:CrmContractTransferReqVO,模块名字要放前面;看看还有没其它类似的 +@Schema(description = "管理后台 - CRM 合同转移 Request VO") +@Data +public class CrmTransferContractReqVO { + + @Schema(description = "合同编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "合同编号不能为空") + private Long id; + + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "新负责人的用户编号不能为空") + private Long ownerUserId; + + @Schema(description = "原负责人移除方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "原负责人移除方式不能为空") + private Integer transferType; + + @Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "权限类型不能为空") + private Integer permissionType; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http new file mode 100644 index 000000000..1dfa2c691 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http @@ -0,0 +1,4 @@ +### 请求 /crm/customer/test 接口 => 成功 +GET {{baseUrl}}/crm/customer/test +tenant-id: 1 +Authorization: Bearer {{token}} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java new file mode 100644 index 000000000..ff144ffbf --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -0,0 +1,98 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; +import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - CRM 客户") +@RestController +@RequestMapping("/crm/customer") +@Validated +public class CrmCustomerController { + + @Resource + private CrmCustomerService customerService; + + @PostMapping("/create") + @Operation(summary = "创建客户") + @PreAuthorize("@ss.hasPermission('crm:customer:create')") + public CommonResult createCustomer(@Valid @RequestBody CrmCustomerCreateReqVO createReqVO) { + return success(customerService.createCustomer(createReqVO, getLoginUserId())); + } + + @PutMapping("/update") + @Operation(summary = "更新客户") + @PreAuthorize("@ss.hasPermission('crm:customer:update')") + public CommonResult updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { + customerService.updateCustomer(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除客户") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:customer:delete')") + public CommonResult deleteCustomer(@RequestParam("id") Long id) { + customerService.deleteCustomer(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得客户") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult getCustomer(@RequestParam("id") Long id) { + CrmCustomerDO customer = customerService.getCustomer(id); + return success(CrmCustomerConvert.INSTANCE.convert(customer)); + } + + @GetMapping("/page") + @Operation(summary = "获得客户分页") + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { + PageResult pageResult = customerService.getCustomerPage(pageVO); + return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出客户 Excel") + @PreAuthorize("@ss.hasPermission('crm:customer:export')") + @OperateLog(type = EXPORT) + public void exportCustomerExcel(@Valid CrmCustomerExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = customerService.getCustomerList(exportReqVO); + // 导出 Excel + List datas = CrmCustomerConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerExcelVO.class, datas); + } + + @PutMapping("/transfer") + @Operation(summary = "客户转移") + @PreAuthorize("@ss.hasPermission('crm:customer:update')") + public CommonResult transfer(@Valid @RequestBody CrmTransferCustomerReqVO reqVO) { + customerService.transferCustomer(reqVO, getLoginUserId()); + return success(true); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java new file mode 100644 index 000000000..0e4d4463d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.framework.common.validation.Telephone; +import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 客户 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class CrmCustomerBaseVO { + + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + @NotEmpty(message = "客户名称不能为空") + private String name; + + @Schema(description = "所属行业", example = "1") + private Integer industryId; + + @Schema(description = "客户等级", example = "2") + @InEnum(CrmCustomerLevelEnum.class) + private Integer level; + + @Schema(description = "客户来源", example = "3") + private Integer source; + + @Schema(description = "手机", example = "18000000000") + @Mobile + private String mobile; + + @Schema(description = "电话", example = "18000000000") + @Telephone + private String telephone; + + @Schema(description = "网址", example = "https://www.baidu.com") + private String website; + + @Schema(description = "QQ", example = "123456789") + @Size(max = 20, message = "QQ长度不能超过 20 个字符") + private String qq; + + @Schema(description = "wechat", example = "123456789") + @Size(max = 255, message = "微信长度不能超过 255 个字符") + private String wechat; + + @Schema(description = "email", example = "123456789@qq.com") + @Email(message = "邮箱格式不正确") + @Size(max = 255, message = "邮箱长度不能超过 255 个字符") + private String email; + + @Schema(description = "客户描述", example = "任意文字") + @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") + private String description; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "地区编号", example = "20158") + private Long areaId; + + @Schema(description = "详细地址", example = "北京市海淀区") + private String detailAddress; + + @Schema(description = "下次联系时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime contactNextTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerCreateReqVO.java new file mode 100644 index 000000000..38108776a --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerCreateReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - CRM 客户创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmCustomerCreateReqVO extends CrmCustomerBaseVO { + + // TODO @wanwan:负责人 + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExcelVO.java new file mode 100644 index 000000000..6f8156175 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExcelVO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +// TODO 芋艿:导出最后做,等基本确认的差不多之后; +/** + * CRM 客户 Excel VO + * + * @author Wanwan + */ +@Data +public class CrmCustomerExcelVO { + + @ExcelProperty("编号") + private Long id; + + @ExcelProperty("客户名称") + private String name; + + @ExcelProperty(value = "跟进状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) + private Boolean followUpStatus; + + @ExcelProperty(value = "锁定状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) + private Boolean lockStatus; + + @ExcelProperty(value = "成交状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.BOOLEAN_STRING) + private Boolean dealStatus; + + @ExcelProperty(value = "所属行业", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY) + private Integer industryId; + + @ExcelProperty(value = "客户等级", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL) + private Integer level; + + @ExcelProperty(value = "客户来源", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) + private Integer source; + + @ExcelProperty("手机") + private String mobile; + + @ExcelProperty("电话") + private String telephone; + + @ExcelProperty("网址") + private String website; + + @ExcelProperty("QQ") + private String qq; + + @ExcelProperty("wechat") + private String wechat; + + @ExcelProperty("email") + private String email; + + @ExcelProperty("客户描述") + private String description; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("负责人的用户编号") + private Long ownerUserId; + + @ExcelProperty("地区编号") + private Long areaId; + + @ExcelProperty("详细地址") + private String detailAddress; + + @ExcelProperty("最后跟进时间") + private LocalDateTime contactLastTime; + + @ExcelProperty("下次联系时间") + private LocalDateTime contactNextTime; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExportReqVO.java new file mode 100644 index 000000000..3a37c2834 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExportReqVO.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +// TODO 芋艿:导出最后做,等基本确认的差不多之后; +@Schema(description = "管理后台 - CRM 客户 Excel 导出 Request VO,参数和 CrmCustomerPageReqVO 是一致的") +@Data +public class CrmCustomerExportReqVO { + + @Schema(description = "客户名称", example = "赵六") + private String name; + + @Schema(description = "手机", example = "18000000000") + private String mobile; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java new file mode 100644 index 000000000..e8a0b9e71 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.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 = "管理后台 - CRM 客户分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmCustomerPageReqVO extends PageParam { + + @Schema(description = "客户名称", example = "赵六") + private String name; + + @Schema(description = "手机", example = "18000000000") + private String mobile; + + // TODO @芋艿:场景; +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java new file mode 100644 index 000000000..505221dfd --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +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 = "管理后台 - CRM 客户 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmCustomerRespVO extends CrmCustomerBaseVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private Long id; + + @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean followUpStatus; + + @Schema(description = "锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean lockStatus; + + @Schema(description = "成交状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean dealStatus; + + @Schema(description = "负责人的用户编号", example = "25682") + private Long ownerUserId; + + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime contactLastTime; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerUpdateReqVO.java new file mode 100644 index 000000000..6ed1566b3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerUpdateReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - CRM 客户更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmCustomerUpdateReqVO extends CrmCustomerBaseVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + @NotNull(message = "编号不能为空") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmTransferCustomerReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmTransferCustomerReqVO.java new file mode 100644 index 000000000..78ca15aca --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmTransferCustomerReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - CRM 客户转移 Request VO") +@Data +public class CrmTransferCustomerReqVO { + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "客户编号不能为空") + private Long id; + + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "新负责人的用户编号不能为空") + private Long ownerUserId; + + @Schema(description = "原负责人移除方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "原负责人移除方式不能为空") + private Integer transferType; + + @Schema(description = "权限类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "权限类型不能为空") + private Integer permissionType; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/package-info.java new file mode 100644 index 000000000..6500da0b8 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/package-info.java @@ -0,0 +1,4 @@ +/** + * 产品表 + */ +package cn.iocoder.yudao.module.crm.controller.admin.product; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/ReceivableController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/ReceivableController.java new file mode 100644 index 000000000..c88f31f6d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/ReceivableController.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.*; +import cn.iocoder.yudao.module.crm.convert.receivable.ReceivableConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivableDO; +import cn.iocoder.yudao.module.crm.service.receivable.ReceivableService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - CRM 回款管理") +@RestController +@RequestMapping("/crm/receivable") +@Validated +public class ReceivableController { + + @Resource + private ReceivableService receivableService; + + @PostMapping("/create") + @Operation(summary = "创建回款管理") + @PreAuthorize("@ss.hasPermission('crm:receivable:create')") + public CommonResult createReceivable(@Valid @RequestBody ReceivableCreateReqVO createReqVO) { + return success(receivableService.createReceivable(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新回款管理") + @PreAuthorize("@ss.hasPermission('crm:receivable:update')") + public CommonResult updateReceivable(@Valid @RequestBody ReceivableUpdateReqVO updateReqVO) { + receivableService.updateReceivable(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除回款管理") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:receivable:delete')") + public CommonResult deleteReceivable(@RequestParam("id") Long id) { + receivableService.deleteReceivable(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得回款管理") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:receivable:query')") + public CommonResult getReceivable(@RequestParam("id") Long id) { + ReceivableDO receivable = receivableService.getReceivable(id); + return success(ReceivableConvert.INSTANCE.convert(receivable)); + } + + @GetMapping("/page") + @Operation(summary = "获得回款管理分页") + @PreAuthorize("@ss.hasPermission('crm:receivable:query')") + public CommonResult> getReceivablePage(@Valid ReceivablePageReqVO pageVO) { + PageResult pageResult = receivableService.getReceivablePage(pageVO); + return success(ReceivableConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出回款管理 Excel") + @PreAuthorize("@ss.hasPermission('crm:receivable:export')") + @OperateLog(type = EXPORT) + public void exportReceivableExcel(@Valid ReceivableExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = receivableService.getReceivableList(exportReqVO); + // 导出 Excel + List datas = ReceivableConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "回款管理.xls", "数据", ReceivableExcelVO.class, datas); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/ReceivablePlanController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/ReceivablePlanController.java new file mode 100644 index 000000000..0c33eb25a --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/ReceivablePlanController.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.*; +import cn.iocoder.yudao.module.crm.convert.receivable.ReceivablePlanConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivablePlanDO; +import cn.iocoder.yudao.module.crm.service.receivable.ReceivablePlanService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - CRM 回款计划") +@RestController +@RequestMapping("/crm/receivable-plan") +@Validated +public class ReceivablePlanController { + + @Resource + private ReceivablePlanService receivablePlanService; + + @PostMapping("/create") + @Operation(summary = "创建回款计划") + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:create')") + public CommonResult createReceivablePlan(@Valid @RequestBody ReceivablePlanCreateReqVO createReqVO) { + return success(receivablePlanService.createReceivablePlan(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新回款计划") + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:update')") + public CommonResult updateReceivablePlan(@Valid @RequestBody ReceivablePlanUpdateReqVO updateReqVO) { + receivablePlanService.updateReceivablePlan(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除回款计划") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:delete')") + public CommonResult deleteReceivablePlan(@RequestParam("id") Long id) { + receivablePlanService.deleteReceivablePlan(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得回款计划") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") + public CommonResult getReceivablePlan(@RequestParam("id") Long id) { + ReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(id); + return success(ReceivablePlanConvert.INSTANCE.convert(receivablePlan)); + } + + @GetMapping("/page") + @Operation(summary = "获得回款计划分页") + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") + public CommonResult> getReceivablePlanPage(@Valid ReceivablePlanPageReqVO pageVO) { + PageResult pageResult = receivablePlanService.getReceivablePlanPage(pageVO); + return success(ReceivablePlanConvert.INSTANCE.convertPage(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出回款计划 Excel") + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:export')") + @OperateLog(type = EXPORT) + public void exportReceivablePlanExcel(@Valid ReceivablePlanExportReqVO exportReqVO, + HttpServletResponse response) throws IOException { + List list = receivablePlanService.getReceivablePlanList(exportReqVO); + // 导出 Excel + List datas = ReceivablePlanConvert.INSTANCE.convertList02(list); + ExcelUtils.write(response, "回款计划.xls", "数据", ReceivablePlanExcelVO.class, datas); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/package-info.java new file mode 100644 index 000000000..199398287 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/package-info.java @@ -0,0 +1,4 @@ +/** + * 回款 + */ +package cn.iocoder.yudao.module.crm.controller.admin.receivable; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableBaseVO.java new file mode 100644 index 000000000..bb0bc5745 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableBaseVO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 回款管理 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class ReceivableBaseVO { + + // TODO @liuhongfeng:部分缺少 example 的字段,要补充下; + // TODO @liuhongfeng:部分字段,需要必传,要写 requiredMode = Schema.RequiredMode.REQUIRED,以及对应的 validator 非空校验 + + @Schema(description = "回款编号") + private String no; + + // TODO @liuhongfeng:中英文之间,有个空格,这样更干净; + @Schema(description = "回款计划ID", example = "31177") + private Long planId; + + @Schema(description = "客户ID", example = "4963") + private Long customerId; + + @Schema(description = "合同ID", example = "30305") + private Long contractId; + + // TODO @liuhongfeng:这个字段,可以写个枚举,然后 InEnum 去校验下; + // TODO @liuhongfeng:这个字段,应该不是前端传递的噢,而是后端自己生成的 + @Schema(description = "审批状态", example = "1") + private Integer checkStatus; + + // TODO @liuhongfeng:这个字段,应该不是前端传递的噢,而是后端自己生成的,所以不适合放在 base 里面; + @Schema(description = "工作流编号", example = "16568") + private Long processInstanceId; + + @Schema(description = "回款日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime returnTime; + + @Schema(description = "回款方式", example = "2") + private String returnType; + + // TODO @liuhongfeng:使用 Int 哈,分; + @Schema(description = "回款金额", example = "31859") + private BigDecimal price; + + @Schema(description = "负责人", example = "22202") + private Long ownerUserId; + + @Schema(description = "批次", example = "2539") + private Long batchId; + + @Schema(description = "显示顺序") + private Integer sort; + + // TODO @芋艿:这个字段在看看;dataScope、dataScopeDeptIds + @Schema(description = "数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)") + private Integer dataScope; + + @Schema(description = "数据范围(指定部门数组)") + private String dataScopeDeptIds; + + // TODO @liuhongfeng:这个字段,这个字段,应该不是前端传递的噢,而是后端自己生成的,所以不适合放在 base 里面; + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableCreateReqVO.java new file mode 100644 index 000000000..d38d0bd5f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - CRM 回款创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReceivableCreateReqVO extends ReceivableBaseVO { + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableExcelVO.java new file mode 100644 index 000000000..b525341d3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableExcelVO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.LocalDateTime; + +import com.alibaba.excel.annotation.ExcelProperty; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + + +/** + * CRM 回款管理 Excel VO + * + * @author 赤焰 + */ +@Data +public class ReceivableExcelVO { + + @ExcelProperty("ID") + private Long id; + + @ExcelProperty("回款编号") + private String no; + + @ExcelProperty("回款计划ID") + private Long planId; + + @ExcelProperty("客户ID") + private Long customerId; + + @ExcelProperty("合同ID") + private Long contractId; + + @ExcelProperty(value = "审批状态", converter = DictConvert.class) + @DictFormat("crm_receivable_check_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中 + private Integer checkStatus; + + @ExcelProperty("工作流编号") + private Long processInstanceId; + + @ExcelProperty("回款日期") + private LocalDateTime returnTime; + + @ExcelProperty("回款方式") + private String returnType; + + @ExcelProperty("回款金额") + private BigDecimal price; + + @ExcelProperty("负责人") + private Long ownerUserId; + + @ExcelProperty("批次") + private Long batchId; + + //@ExcelProperty("显示顺序") + //private Integer sort; + + //@ExcelProperty("数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)") + //private Integer dataScope; + + //@ExcelProperty("数据范围(指定部门数组)") + //private String dataScopeDeptIds; + + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中 + private Integer status; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableExportReqVO.java new file mode 100644 index 000000000..4a9a033f3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableExportReqVO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * @author 赤焰 + */ +@Schema(description = "管理后台 - CRM 回款 Excel 导出 Request VO,参数和 ReceivablePageReqVO 是一致的") +@Data +public class ReceivableExportReqVO { + + @Schema(description = "回款编号") + private String no; + + @Schema(description = "回款计划ID", example = "31177") + private Long planId; + + @Schema(description = "客户ID", example = "4963") + private Long customerId; + + @Schema(description = "合同ID", example = "30305") + private Long contractId; + + @Schema(description = "审批状态", example = "1") + private Integer checkStatus; + + @Schema(description = "工作流编号", example = "16568") + private Long processInstanceId; + + @Schema(description = "回款日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnTime; + + @Schema(description = "回款方式", example = "2") + private String returnType; + + @Schema(description = "回款金额", example = "31859") + private BigDecimal price; + + @Schema(description = "负责人", example = "22202") + private Long ownerUserId; + + @Schema(description = "批次", example = "2539") + private Long batchId; + + @Schema(description = "显示顺序") + private Integer sort; + + @Schema(description = "数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)") + private Integer dataScope; + + @Schema(description = "数据范围(指定部门数组)") + private String dataScopeDeptIds; + + @Schema(description = "状态", example = "1") + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePageReqVO.java new file mode 100644 index 000000000..ba4775535 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePageReqVO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.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.math.BigDecimal; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - CRM 回款分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReceivablePageReqVO extends PageParam { + + // TODO @liuhongfeng:目前就使用 no 检索即可; + @Schema(description = "回款编号") + private String no; + + @Schema(description = "回款计划ID", example = "31177") + private Long planId; + + @Schema(description = "客户ID", example = "4963") + private Long customerId; + + @Schema(description = "合同ID", example = "30305") + private Long contractId; + + @Schema(description = "审批状态", example = "1") + private Integer checkStatus; + + @Schema(description = "工作流编号", example = "16568") + private Long processInstanceId; + + @Schema(description = "回款日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnTime; + + @Schema(description = "回款方式", example = "2") + private String returnType; + + @Schema(description = "回款金额", example = "31859") + private BigDecimal price; + + @Schema(description = "负责人", example = "22202") + private Long ownerUserId; + + @Schema(description = "批次", example = "2539") + private Long batchId; + + @Schema(description = "显示顺序") + private Integer sort; + + @Schema(description = "数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)") + private Integer dataScope; + + @Schema(description = "数据范围(指定部门数组)") + private String dataScopeDeptIds; + + @Schema(description = "状态", example = "1") + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanBaseVO.java new file mode 100644 index 000000000..59f333e4b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanBaseVO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 回款计划 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class ReceivablePlanBaseVO { + + // TODO 芋艿:这个字段,在想想命名; + @Schema(description = "期数") + private Long indexNo; + + // TODO @liuhongfeng:中英文之间,有个空格,这样更干净; + @Schema(description = "回款ID", example = "19852") + private Long receivableId; + + @Schema(description = "完成状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + //@NotNull(message = "完成状态不能为空") + private Integer status; + + // TODO @liuhongfeng:这个字段,可以写个枚举,然后 InEnum 去校验下; + // TODO @liuhongfeng:这个字段,应该不是前端传递的噢,而是后端自己生成的 + @Schema(description = "审批状态", example = "1") + private String checkStatus; + + // TODO @liuhongfeng:这个字段,应该不是前端传递的噢,而是后端自己生成的,所以不适合放在 base 里面; + @Schema(description = "工作流编号", example = "8909") + private Long processInstanceId; + + // TODO @liuhongfeng:使用 Int 哈,分; + @Schema(description = "计划回款金额", example = "29675") + private BigDecimal price; + + @Schema(description = "计划回款日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime returnTime; + + // TODO @liuhongfeng:这个字段,Integer + @Schema(description = "提前几天提醒") + private Long remindDays; + + @Schema(description = "提醒日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime remindTime; + + @Schema(description = "客户ID", example = "18026") + private Long customerId; + + @Schema(description = "合同ID", example = "3473") + private Long contractId; + + // TODO @liuhongfeng:这个字段,应该不是前端传递的噢,而是后端自己生成的,所以不适合放在 base 里面; + @Schema(description = "负责人", example = "17828") + private Long ownerUserId; + + @Schema(description = "显示顺序") + private Integer sort; + + @Schema(description = "备注", example = "随便") + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanCreateReqVO.java new file mode 100644 index 000000000..d03e76eb0 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanCreateReqVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - CRM 回款计划创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReceivablePlanCreateReqVO extends ReceivablePlanBaseVO { + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanExcelVO.java new file mode 100644 index 000000000..f0b822115 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanExcelVO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import com.alibaba.excel.annotation.ExcelProperty; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + + +/** + * CRM 回款计划 Excel VO + * + * @author 芋道源码 + */ +@Data +public class ReceivablePlanExcelVO { + + @ExcelProperty("ID") + private Long id; + + @ExcelProperty("期数") + private Long indexNo; + + @ExcelProperty("回款ID") + private Long receivableId; + + @ExcelProperty(value = "完成状态", converter = DictConvert.class) + @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中 + private Integer status; + + @ExcelProperty(value = "审批状态", converter = DictConvert.class) + @DictFormat("crm_receivable_check_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中 + private String checkStatus; + + //@ExcelProperty("工作流编号") + //private Long processInstanceId; + + @ExcelProperty("计划回款金额") + private BigDecimal price; + + @ExcelProperty("计划回款日期") + private LocalDateTime returnTime; + + @ExcelProperty("提前几天提醒") + private Long remindDays; + + @ExcelProperty("提醒日期") + private LocalDateTime remindTime; + + @ExcelProperty("客户ID") + private Long customerId; + + @ExcelProperty("合同ID") + private Long contractId; + + @ExcelProperty("负责人") + private Long ownerUserId; + + //@ExcelProperty("显示顺序") + //private Integer sort; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanExportReqVO.java new file mode 100644 index 000000000..506ffa1ed --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanExportReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.time.LocalDateTime; +import org.springframework.format.annotation.DateTimeFormat; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - CRM 回款计划 Excel 导出 Request VO,参数和 ReceivablePlanPageReqVO 是一致的") +@Data +public class ReceivablePlanExportReqVO { + + @Schema(description = "期数") + private Long indexNo; + + @Schema(description = "完成状态", example = "2") + private Integer status; + + @Schema(description = "审批状态", example = "1") + private String checkStatus; + + @Schema(description = "计划回款日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnTime; + + @Schema(description = "提前几天提醒") + private Long remindDays; + + @Schema(description = "提醒日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] remindTime; + + @Schema(description = "客户ID", example = "18026") + private Long customerId; + + @Schema(description = "合同ID", example = "3473") + private Long contractId; + + @Schema(description = "负责人", example = "17828") + private Long ownerUserId; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanPageReqVO.java new file mode 100644 index 000000000..16ad6353d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanPageReqVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.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 = "管理后台 - CRM 回款计划分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReceivablePlanPageReqVO extends PageParam { + + // TODO 芋艿:筛选字段,需要去掉几个,在想想; + + @Schema(description = "期数") + private Long indexNo; + + @Schema(description = "完成状态", example = "2") + private Integer status; + + @Schema(description = "审批状态", example = "1") + private String checkStatus; + + @Schema(description = "计划回款日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnTime; + + @Schema(description = "提前几天提醒") + private Long remindDays; + + @Schema(description = "提醒日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] remindTime; + + @Schema(description = "客户ID", example = "18026") + private Long customerId; + + @Schema(description = "合同ID", example = "3473") + private Long contractId; + + @Schema(description = "负责人", example = "17828") + private Long ownerUserId; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanRespVO.java new file mode 100644 index 000000000..ce49d5977 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 回款计划 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReceivablePlanRespVO extends ReceivablePlanBaseVO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25153") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanUpdateReqVO.java new file mode 100644 index 000000000..1f539537d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivablePlanUpdateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - CRM 回款计划更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReceivablePlanUpdateReqVO extends ReceivablePlanBaseVO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25153") + @NotNull(message = "ID不能为空") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableRespVO.java new file mode 100644 index 000000000..1646cd5a8 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 回款 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReceivableRespVO extends ReceivableBaseVO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25787") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableUpdateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableUpdateReqVO.java new file mode 100644 index 000000000..008c06b63 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/ReceivableUpdateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import javax.validation.constraints.*; + +@Schema(description = "管理后台 - CRM 回款更新 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ReceivableUpdateReqVO extends ReceivableBaseVO { + + @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25787") + @NotNull(message = "ID不能为空") + private Long id; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/app/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/app/package-info.java new file mode 100644 index 000000000..78d85635c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/app/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位 + */ +package cn.iocoder.yudao.module.crm.controller.app; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java new file mode 100644 index 000000000..8354b3176 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/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.crm.controller; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java new file mode 100644 index 000000000..b9ddf8496 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.crm.convert.business; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 商机 Convert + * + * @author ljlleo + */ +@Mapper +public interface CrmBusinessConvert { + + CrmBusinessConvert INSTANCE = Mappers.getMapper(CrmBusinessConvert.class); + + CrmBusinessDO convert(CrmBusinessCreateReqVO bean); + + CrmBusinessDO convert(CrmBusinessUpdateReqVO bean); + + CrmBusinessRespVO convert(CrmBusinessDO bean); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + + @Mappings({ + @Mapping(target = "userId", source = "userId"), + @Mapping(target = "crmDataId", source = "reqVO.id") + }) + TransferCrmPermissionBO convert(CrmTransferBusinessReqVO reqVO, Long userId); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java new file mode 100644 index 000000000..c8b854144 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.crm.convert.businessstatus; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO; + +/** + * 商机状态 Convert + * + * @author ljlleo + */ +@Mapper +public interface CrmBusinessStatusConvert { + + CrmBusinessStatusConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusConvert.class); + + CrmBusinessStatusDO convert(CrmBusinessStatusCreateReqVO bean); + + CrmBusinessStatusDO convert(CrmBusinessStatusUpdateReqVO bean); + + CrmBusinessStatusRespVO convert(CrmBusinessStatusDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java new file mode 100644 index 000000000..75f1aed4c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.crm.convert.businessstatustype; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO; + +/** + * 商机状态类型 Convert + * + * @author ljlleo + */ +@Mapper +public interface CrmBusinessStatusTypeConvert { + + CrmBusinessStatusTypeConvert INSTANCE = Mappers.getMapper(CrmBusinessStatusTypeConvert.class); + + CrmBusinessStatusTypeDO convert(CrmBusinessStatusTypeCreateReqVO bean); + + CrmBusinessStatusTypeDO convert(CrmBusinessStatusTypeUpdateReqVO bean); + + CrmBusinessStatusTypeRespVO convert(CrmBusinessStatusTypeDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java new file mode 100644 index 000000000..76ea428c7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.crm.convert.clue; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; + +/** + * 线索 Convert + * + * @author Wanwan + */ +@Mapper +public interface CrmClueConvert { + + CrmClueConvert INSTANCE = Mappers.getMapper(CrmClueConvert.class); + + CrmClueDO convert(CrmClueCreateReqVO bean); + + CrmClueDO convert(CrmClueUpdateReqVO bean); + + CrmClueRespVO convert(CrmClueDO bean); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java new file mode 100644 index 000000000..11b549062 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.crm.convert.contact; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO; +import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * crm 联系人 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ContactConvert { + + ContactConvert INSTANCE = Mappers.getMapper(ContactConvert.class); + + ContactDO convert(ContactCreateReqVO bean); + + ContactDO convert(ContactUpdateReqVO bean); + + ContactRespVO convert(ContactDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + + @Mappings({ + @Mapping(target = "userId", source = "userId"), + @Mapping(target = "crmDataId", source = "reqVO.id") + }) + TransferCrmPermissionBO convert(CrmTransferContactReqVO reqVO, Long userId); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java new file mode 100644 index 000000000..bad9fa573 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.crm.convert.contract; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO; +import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 合同 Convert + * + * @author dhb52 + */ +@Mapper +public interface ContractConvert { + + ContractConvert INSTANCE = Mappers.getMapper(ContractConvert.class); + + ContractDO convert(ContractCreateReqVO bean); + + ContractDO convert(ContractUpdateReqVO bean); + + ContractRespVO convert(ContractDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + + @Mappings({ + @Mapping(target = "userId", source = "userId"), + @Mapping(target = "crmDataId", source = "reqVO.id") + }) + TransferCrmPermissionBO convert(CrmTransferContractReqVO reqVO, Long userId); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java new file mode 100644 index 000000000..7072536f5 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.crm.convert.customer; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +/** + * 客户 Convert + * + * @author Wanwan + */ +@Mapper +public interface CrmCustomerConvert { + + CrmCustomerConvert INSTANCE = Mappers.getMapper(CrmCustomerConvert.class); + + CrmCustomerDO convert(CrmCustomerCreateReqVO bean); + + CrmCustomerDO convert(CrmCustomerUpdateReqVO bean); + + CrmCustomerRespVO convert(CrmCustomerDO bean); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + + @Mappings({ + @Mapping(target = "userId", source = "userId"), + @Mapping(target = "crmDataId", source = "reqVO.id") + }) + TransferCrmPermissionBO convert(CrmTransferCustomerReqVO reqVO, Long userId); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/package-info.java new file mode 100644 index 000000000..6fbc52508 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 POJO 类的实体转换 + * + * 目前使用 MapStruct 框架 + */ +package cn.iocoder.yudao.module.crm.convert; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java new file mode 100644 index 000000000..0fc6f61cc --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.crm.convert.permission; + +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateBO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * Crm 数据权限 Convert + * + * @author Wanwan + */ +@Mapper +public interface CrmPermissionConvert { + + CrmPermissionConvert INSTANCE = Mappers.getMapper(CrmPermissionConvert.class); + + CrmPermissionDO convert(CrmPermissionCreateBO createBO); + + CrmPermissionDO convert(CrmPermissionUpdateBO updateBO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/ReceivableConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/ReceivableConvert.java new file mode 100644 index 000000000..7f14aaddd --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/ReceivableConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.crm.convert.receivable; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivableDO; + +/** + * 回款管理 Convert + * + * @author 赤焰 + */ +@Mapper +public interface ReceivableConvert { + + ReceivableConvert INSTANCE = Mappers.getMapper(ReceivableConvert.class); + + ReceivableDO convert(ReceivableCreateReqVO bean); + + ReceivableDO convert(ReceivableUpdateReqVO bean); + + ReceivableRespVO convert(ReceivableDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/ReceivablePlanConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/ReceivablePlanConvert.java new file mode 100644 index 000000000..81ec646f3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/ReceivablePlanConvert.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.crm.convert.receivable; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivablePlanDO; + +/** + * 回款计划 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface ReceivablePlanConvert { + + ReceivablePlanConvert INSTANCE = Mappers.getMapper(ReceivablePlanConvert.class); + + ReceivablePlanDO convert(ReceivablePlanCreateReqVO bean); + + ReceivablePlanDO convert(ReceivablePlanUpdateReqVO bean); + + ReceivablePlanRespVO convert(ReceivablePlanDO bean); + + List convertList(List list); + + PageResult convertPage(PageResult page); + + List convertList02(List list); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md new file mode 100644 index 000000000..8153487b7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java new file mode 100644 index 000000000..435bf1995 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.business; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO; +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 ljlleo + */ +@TableName("crm_business") +@KeySequence("crm_business_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmBusinessDO extends BaseDO { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 商机名称 + */ + private String name; + /** + * 商机状态类型编号 + * + * 关联 {@link CrmBusinessStatusTypeDO#getId()} + */ + private Long statusTypeId; + /** + * 商机状态编号 + * + * 关联 {@link CrmBusinessStatusDO#getId()} + */ + private Long statusId; + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; + /** + * 客户编号 + * + * TODO @ljileo:这个字段,后续要写下关联的实体哈 + */ + private Long customerId; + /** + * 预计成交日期 + */ + private LocalDateTime dealTime; + /** + * 商机金额 + * + */ + private Integer price; + /** + * 整单折扣 + * + */ + private Integer discountPercent; + /** + * 产品总金额 + * + */ + private Integer productPrice; + /** + * 备注 + */ + private String remark; + /** + * 1赢单2输单3无效 + * + * TODO @lijie:搞个枚举; + */ + private Integer endStatus; + /** + * 结束时的备注 + */ + private String endRemark; + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + /** + * 跟进状态 + * + * TODO @lijie:目前就是 Boolean;是否跟进 + */ + private Integer followUpStatus; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/package-info.java new file mode 100644 index 000000000..df6e44536 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/package-info.java @@ -0,0 +1,4 @@ +/** + * 商机(销售机会) + */ +package cn.iocoder.yudao.module.crm.dal.dataobject.business; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/businessstatus/CrmBusinessStatusDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/businessstatus/CrmBusinessStatusDO.java new file mode 100644 index 000000000..3a1b66ad0 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/businessstatus/CrmBusinessStatusDO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商机状态 DO + * + * @author ljlleo + */ +@TableName("crm_business_status") +@KeySequence("crm_business_status_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmBusinessStatusDO { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 状态类型编号 + * + * // TODO @ljlleo:要写下关联字段噢 + */ + private Long typeId; + /** + * 状态名 + */ + private String name; + /** + * 赢单率 + */ + private String percent; + /** + * 排序 + */ + private Integer sort; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/businessstatustype/CrmBusinessStatusTypeDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/businessstatustype/CrmBusinessStatusTypeDO.java new file mode 100644 index 000000000..fbc2e6857 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/businessstatustype/CrmBusinessStatusTypeDO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 商机状态类型 DO + * + * @author ljlleo + */ +@TableName("crm_business_status_type") +@KeySequence("crm_business_status_type_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmBusinessStatusTypeDO { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 状态类型名 + */ + private String name; + // TODO @ljlleo:List 存储哈 + /** + * 使用的部门编号 + */ + private String deptIds; + /** + * 开启状态 + */ + // TODO @ljlleo:这个字段,使用 Integer,对应 CommonStatus + private Boolean status; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java new file mode 100644 index 000000000..592301b44 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.clue; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +// TODO 芋艿:字段的顺序,需要整理下; +/** + * 线索 DO + * + * @author Wanwan + */ +@TableName("crm_clue") +@KeySequence("crm_clue_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmClueDO extends BaseDO { + + /** + * 编号,主键自增 + */ + @TableId + private Long id; + /** + * 转化状态 + */ + private Boolean transformStatus; + /** + * 跟进状态 + */ + private Boolean followUpStatus; + /** + * 线索名称 + */ + private String name; + /** + * 客户 id + * + * 关联 {@link CrmCustomerDO#getId()} + */ + private Long customerId; + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; + /** + * 电话 + */ + private String telephone; + /** + * 手机号 + */ + private String mobile; + /** + * 地址 + */ + private String address; + /** + * 最后跟进时间 TODO 添加跟进记录时更新该值 + */ + private LocalDateTime contactLastTime; + /** + * 备注 + */ + private String remark; + + // TODO 芋艿:客户级别; + // TODO 芋艿:线索来源; + // TODO 芋艿:客户行业; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/package-info.java new file mode 100644 index 000000000..929b9b6fe --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/package-info.java @@ -0,0 +1,4 @@ +/** + * 线索 + */ +package cn.iocoder.yudao.module.crm.dal.dataobject.clue; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/ContactDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/ContactDO.java new file mode 100644 index 000000000..f958fcd64 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/ContactDO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.contact; + +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; + +/** + * crm 联系人 DO + * + * @author 芋道源码 + */ +@TableName("crm_contact") +@KeySequence("crm_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ContactDO extends BaseDO { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 联系人名称 + */ + private String name; + /** + * 下次联系时间 + */ + private LocalDateTime nextTime; + /** + * 手机号 + */ + private String mobile; + /** + * 电话 + */ + private String telephone; + /** + * 电子邮箱 + */ + private String email; + /** + * 职务 + */ + private String post; + /** + * 客户编号 + * + * TODO @zyna:关联的字段,也要写下 + */ + private Long customerId; + /** + * 地址 + */ + private String address; + /** + * 备注 + */ + private String remark; + /** + * 最后跟进时间 + */ + private LocalDateTime lastTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/package-info.java new file mode 100644 index 000000000..dfe0898e3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/package-info.java @@ -0,0 +1,4 @@ +/** + * 联系人 + */ +package cn.iocoder.yudao.module.crm.dal.dataobject.contact; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/ContractDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/ContractDO.java new file mode 100644 index 000000000..f32786791 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/ContractDO.java @@ -0,0 +1,92 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.contract; + +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; + +/** + * 合同 DO + * + * @author dhb52 + */ +@TableName("crm_contract") +@KeySequence("crm_contract_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ContractDO extends BaseDO { + + /** + * 合同编号 + */ + @TableId + private Long id; + /** + * 合同名称 + */ + private String name; + /** + * 客户编号 + */ + private Long customerId; + /** + * 商机编号 + */ + private Long businessId; + /** + * 工作流编号 + */ + private Long processInstanceId; + /** + * 下单日期 + */ + private LocalDateTime orderDate; + /** + * 合同编号 + */ + private String no; + /** + * 开始时间 + */ + private LocalDateTime startTime; + /** + * 结束时间 + */ + private LocalDateTime endTime; + /** + * 合同金额 + */ + private Integer price; + /** + * 整单折扣 + */ + private Integer discountPercent; + /** + * 产品总金额 + */ + private Integer productPrice; + /** + * 联系人编号 + */ + private Long contactId; + /** + * 公司签约人 + */ + private Long signUserId; + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/package-info.java new file mode 100644 index 000000000..a981b5dfc --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/package-info.java @@ -0,0 +1,4 @@ +/** + * 合同 + */ +package cn.iocoder.yudao.module.crm.dal.dataobject.contract; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java new file mode 100644 index 000000000..9de87ee5b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -0,0 +1,116 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.customer; + +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; + +// TODO 芋艿:调整下字段 + +/** + * 客户 DO + * + * @author Wanwan + */ +@TableName(value = "crm_customer", autoResultMap = true) +@KeySequence("crm_customer_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmCustomerDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 客户名称 + */ + private String name; + /** + * 跟进状态 + */ + private Boolean followUpStatus; + /** + * 锁定状态 + */ + private Boolean lockStatus; + /** + * 成交状态 + */ + private Boolean dealStatus; + /** + * 所属行业 + * + * 对应字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_CUSTOMER_INDUSTRY} + */ + private Integer industryId; + /** + * 客户等级 + * + * 对应字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_CUSTOMER_LEVEL} + */ + private Integer level; + /** + * 客户来源 + * + * 对应字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_CUSTOMER_SOURCE} + */ + private Integer source; + /** + * 手机 + */ + private String mobile; + /** + * 电话 + */ + private String telephone; + /** + * 网址 + */ + private String website; + /** + * QQ + */ + private String qq; + /** + * wechat + */ + private String wechat; + /** + * email + */ + private String email; + /** + * 客户描述 + */ + private String description; + /** + * 备注 + */ + private String remark; + /** + * 地区编号 + */ + private Long areaId; + /** + * 详细地址 + */ + private String detailAddress; + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/package-info.java new file mode 100644 index 000000000..78e98bcd9 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/package-info.java @@ -0,0 +1,4 @@ +/** + * 客户 + */ +package cn.iocoder.yudao.module.crm.dal.dataobject.customer; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java new file mode 100644 index 000000000..028d41c95 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.permission; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +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.Set; + +/** + * crm 数据权限 DO + * + * @author HUIHUI + */ +@TableName("crm_receivable") +@KeySequence("crm_receivable_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmPermissionDO extends BaseDO { + + /** + * ID + */ + @TableId + private Long id; + /** + * 数据类型 关联 {@link CrmEnum} + */ + private Integer crmType; + /** + * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId() + */ + private Long crmDataId; + /** + * 负责人的用户编号 关联 AdminUser#id + */ + private Long ownerUserId; + /** + * 只读权限的用户编号数组 + */ + @TableField(typeHandler = JsonLongSetTypeHandler.class) + private Set roUserIds; + /** + * 读写权限的用户编号数组 + */ + @TableField(typeHandler = JsonLongSetTypeHandler.class) + private Set rwUserIds; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/package-info.java new file mode 100644 index 000000000..4c7282d73 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/package-info.java @@ -0,0 +1,4 @@ +/** + * 产品表 + */ +package cn.iocoder.yudao.module.crm.dal.dataobject.product; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/ReceivableDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/ReceivableDO.java new file mode 100644 index 000000000..d80f76a91 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/ReceivableDO.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.receivable; + +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; +import java.time.LocalDateTime; + +/** + * 回款管理 DO + * + * @author 赤焰 + */ +@TableName("crm_receivable") +@KeySequence("crm_receivable_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReceivableDO extends BaseDO { + + /** + * ID + */ + @TableId + private Long id; + /** + * 回款编号 + */ + private String no; + /** + * 回款计划ID + * + * TODO @liuhongfeng:这个字段,后续要写下关联的实体哈 + */ + private Long planId; + /** + * 客户ID + * + * TODO @liuhongfeng:这个字段,后续要写下关联的实体哈 + */ + private Long customerId; + /** + * 合同ID + * + * TODO @liuhongfeng:这个字段,后续要写下关联的实体哈 + */ + private Long contractId; + /** + * 审批状态 + * + * 枚举 {@link TODO crm_receivable_check_status 对应的类} + */ + private Integer checkStatus; + /** + * 工作流编号 + * + * TODO @liuhongfeng:这个字段,后续要写下关联的实体哈 + */ + private Long processInstanceId; + /** + * 回款日期 + */ + private LocalDateTime returnTime; + /** + * 回款方式 + */ + private String returnType; + /** + * 回款金额 + */ + private BigDecimal price; + /** + * 负责人 + */ + private Long ownerUserId; + /** + * 批次 + */ + private Long batchId; + /** + * 显示顺序 + */ + private Integer sort; + // TODO 芋艿:dataScope、dataScopeDeptIds 在想下; + /** + * 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) + */ + private Integer dataScope; + /** + * 数据范围(指定部门数组) + */ + private String dataScopeDeptIds; + /** + * 状态 + * + * 枚举 {@link TODO common_status 对应的类} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/ReceivablePlanDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/ReceivablePlanDO.java new file mode 100644 index 000000000..4447df053 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/ReceivablePlanDO.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.receivable; + +import lombok.*; +import java.util.*; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 回款计划 DO + * + * @author 芋道源码 + */ +@TableName("crm_receivable_plan") +@KeySequence("crm_receivable_plan_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReceivablePlanDO extends BaseDO { + + /** + * ID + */ + @TableId + private Long id; + /** + * 期数 + */ + private Long indexNo; + /** + * 回款ID + */ + private Long receivableId; + /** + * 完成状态 + * + * 枚举 {@link TODO common_status 对应的类} + */ + private Integer status; + /** + * 审批状态 + * + * 枚举 {@link TODO crm_receivable_check_status 对应的类} + */ + private String checkStatus; + /** + * 工作流编号 + */ + private Long processInstanceId; + /** + * 计划回款金额 + */ + private BigDecimal price; + /** + * 计划回款日期 + */ + private LocalDateTime returnTime; + /** + * 提前几天提醒 + */ + private Long remindDays; + /** + * 提醒日期 + */ + private LocalDateTime remindTime; + /** + * 客户ID + */ + private Long customerId; + /** + * 合同ID + */ + private Long contractId; + /** + * 负责人 + */ + private Long ownerUserId; + /** + * 显示顺序 + */ + private Integer sort; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/package-info.java new file mode 100644 index 000000000..f27442cdf --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/package-info.java @@ -0,0 +1,4 @@ +/** + * 回款 + */ +package cn.iocoder.yudao.module.crm.dal.dataobject.receivable; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java new file mode 100644 index 000000000..5df94c0fa --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.business; + +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.crm.controller.admin.business.vo.CrmBusinessExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.CrmBusinessPageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 商机 Mapper + * + * @author ljlleo + */ +@Mapper +public interface CrmBusinessMapper extends BaseMapperX { + + default PageResult selectPage(CrmBusinessPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(CrmBusinessDO::getName, reqVO.getName()) + .orderByDesc(CrmBusinessDO::getId)); + } + + default List selectList(CrmBusinessExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(CrmBusinessDO::getName, reqVO.getName()) + .eqIfPresent(CrmBusinessDO::getStatusTypeId, reqVO.getStatusTypeId()) + .eqIfPresent(CrmBusinessDO::getStatusId, reqVO.getStatusId()) + .betweenIfPresent(CrmBusinessDO::getContactNextTime, reqVO.getContactNextTime()) + .eqIfPresent(CrmBusinessDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(CrmBusinessDO::getDealTime, reqVO.getDealTime()) + .eqIfPresent(CrmBusinessDO::getPrice, reqVO.getPrice()) + .eqIfPresent(CrmBusinessDO::getDiscountPercent, reqVO.getDiscountPercent()) + .eqIfPresent(CrmBusinessDO::getProductPrice, reqVO.getProductPrice()) + .eqIfPresent(CrmBusinessDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(CrmBusinessDO::getCreateTime, reqVO.getCreateTime()) + .eqIfPresent(CrmBusinessDO::getEndStatus, reqVO.getEndStatus()) + .eqIfPresent(CrmBusinessDO::getEndRemark, reqVO.getEndRemark()) + .betweenIfPresent(CrmBusinessDO::getContactLastTime, reqVO.getContactLastTime()) + .eqIfPresent(CrmBusinessDO::getFollowUpStatus, reqVO.getFollowUpStatus()) + .orderByDesc(CrmBusinessDO::getId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/package-info.java new file mode 100644 index 000000000..72863e1f4 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/package-info.java @@ -0,0 +1,4 @@ +/** + * 商机(销售机会) + */ +package cn.iocoder.yudao.module.crm.dal.mysql.business; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/businessstatus/CrmBusinessStatusMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/businessstatus/CrmBusinessStatusMapper.java new file mode 100644 index 000000000..2b9eeb4ae --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/businessstatus/CrmBusinessStatusMapper.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.businessstatus; + +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.crm.controller.admin.businessstatus.vo.CrmBusinessStatusExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusPageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 商机状态 Mapper + * + * @author ljlleo + */ +@Mapper +public interface CrmBusinessStatusMapper extends BaseMapperX { + + default PageResult selectPage(CrmBusinessStatusPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(CrmBusinessStatusDO::getTypeId, reqVO.getTypeId()) + .orderByDesc(CrmBusinessStatusDO::getId)); + } + + default List selectList(CrmBusinessStatusExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(CrmBusinessStatusDO::getTypeId, reqVO.getTypeId()) + .likeIfPresent(CrmBusinessStatusDO::getName, reqVO.getName()) + .eqIfPresent(CrmBusinessStatusDO::getPercent, reqVO.getPercent()) + .eqIfPresent(CrmBusinessStatusDO::getSort, reqVO.getSort()) + .orderByDesc(CrmBusinessStatusDO::getId)); + } + + default List getBusinessStatusListByTypeId(Integer typeId) { + return selectList(CrmBusinessStatusDO::getTypeId, typeId); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/businessstatustype/CrmBusinessStatusTypeMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/businessstatustype/CrmBusinessStatusTypeMapper.java new file mode 100644 index 000000000..258477e4d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/businessstatustype/CrmBusinessStatusTypeMapper.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.businessstatustype; + +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.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypePageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 商机状态类型 Mapper + * + * @author ljlleo + */ +@Mapper +public interface CrmBusinessStatusTypeMapper extends BaseMapperX { + + default PageResult selectPage(CrmBusinessStatusTypePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(CrmBusinessStatusTypeDO::getName, reqVO.getName()) +// .eqIfPresent(CrmBusinessStatusTypeDO::getDeptIds, reqVO.getDeptIds()) TODO 报错,临时注释掉 + .eqIfPresent(CrmBusinessStatusTypeDO::getStatus, reqVO.getStatus()) + .orderByDesc(CrmBusinessStatusTypeDO::getId)); + } + + default List selectList(CrmBusinessStatusTypeExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(CrmBusinessStatusTypeDO::getName, reqVO.getName()) + .eqIfPresent(CrmBusinessStatusTypeDO::getDeptIds, reqVO.getDeptIds()) + .eqIfPresent(CrmBusinessStatusTypeDO::getStatus, reqVO.getStatus()) + .orderByDesc(CrmBusinessStatusTypeDO::getId)); + } + + default List getBusinessStatusTypeListByStatus(Integer status) { + return selectList(CrmBusinessStatusTypeDO::getStatus, status.byteValue()); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java new file mode 100644 index 000000000..8f9fea6c3 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.clue; + +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.crm.controller.admin.clue.vo.CrmClueExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 线索 Mapper + * + * @author Wanwan + */ +@Mapper +public interface CrmClueMapper extends BaseMapperX { + + default PageResult selectPage(CrmCluePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(CrmClueDO::getName, reqVO.getName()) + .likeIfPresent(CrmClueDO::getTelephone, reqVO.getTelephone()) + .likeIfPresent(CrmClueDO::getMobile, reqVO.getMobile()) + .orderByDesc(CrmClueDO::getId)); + } + + default List selectList(CrmClueExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(CrmClueDO::getTransformStatus, reqVO.getTransformStatus()) + .eqIfPresent(CrmClueDO::getFollowUpStatus, reqVO.getFollowUpStatus()) + .likeIfPresent(CrmClueDO::getName, reqVO.getName()) + .eqIfPresent(CrmClueDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(CrmClueDO::getContactNextTime, reqVO.getContactNextTime()) + .likeIfPresent(CrmClueDO::getTelephone, reqVO.getTelephone()) + .likeIfPresent(CrmClueDO::getMobile, reqVO.getMobile()) + .likeIfPresent(CrmClueDO::getAddress, reqVO.getAddress()) + .betweenIfPresent(CrmClueDO::getContactLastTime, reqVO.getContactLastTime()) + .betweenIfPresent(CrmClueDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(CrmClueDO::getId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/package-info.java new file mode 100644 index 000000000..f9978e868 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/package-info.java @@ -0,0 +1,4 @@ +/** + * 线索 + */ +package cn.iocoder.yudao.module.crm.dal.mysql.clue; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/ContactMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/ContactMapper.java new file mode 100644 index 000000000..7643e4d4c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/ContactMapper.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.contact; + +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.crm.controller.admin.contact.vo.ContactExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.ContactPageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * crm联系人 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ContactMapper extends BaseMapperX { + + default PageResult selectPage(ContactPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ContactDO::getName, reqVO.getName()) + .betweenIfPresent(ContactDO::getNextTime, reqVO.getNextTime()) + .eqIfPresent(ContactDO::getMobile, reqVO.getMobile()) + .eqIfPresent(ContactDO::getTelephone, reqVO.getTelephone()) + .eqIfPresent(ContactDO::getEmail, reqVO.getEmail()) + .eqIfPresent(ContactDO::getPost, reqVO.getPost()) + .eqIfPresent(ContactDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ContactDO::getAddress, reqVO.getAddress()) + .eqIfPresent(ContactDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(ContactDO::getCreateTime, reqVO.getCreateTime()) + .betweenIfPresent(ContactDO::getLastTime, reqVO.getLastTime()) + .orderByDesc(ContactDO::getId)); + } + + default List selectList(ContactExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(ContactDO::getName, reqVO.getName()) + .betweenIfPresent(ContactDO::getNextTime, reqVO.getNextTime()) + .eqIfPresent(ContactDO::getMobile, reqVO.getMobile()) + .eqIfPresent(ContactDO::getTelephone, reqVO.getTelephone()) + .eqIfPresent(ContactDO::getEmail, reqVO.getEmail()) + .eqIfPresent(ContactDO::getPost, reqVO.getPost()) + .eqIfPresent(ContactDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ContactDO::getAddress, reqVO.getAddress()) + .eqIfPresent(ContactDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(ContactDO::getCreateTime, reqVO.getCreateTime()) + .betweenIfPresent(ContactDO::getLastTime, reqVO.getLastTime()) + .orderByDesc(ContactDO::getId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/package-info.java new file mode 100644 index 000000000..6cb7d4be2 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/package-info.java @@ -0,0 +1,4 @@ +/** + * 联系人 + */ +package cn.iocoder.yudao.module.crm.dal.mysql.contact; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/ContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/ContractMapper.java new file mode 100644 index 000000000..47337518b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/ContractMapper.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.contract; + +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.crm.controller.admin.contract.vo.ContractExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 合同 Mapper + * + * @author dhb52 + */ +@Mapper +public interface ContractMapper extends BaseMapperX { + + default PageResult selectPage(ContractPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ContractDO::getName, reqVO.getName()) + .eqIfPresent(ContractDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ContractDO::getBusinessId, reqVO.getBusinessId()) + .betweenIfPresent(ContractDO::getOrderDate, reqVO.getOrderDate()) + .eqIfPresent(ContractDO::getNo, reqVO.getNo()) + .eqIfPresent(ContractDO::getDiscountPercent, reqVO.getDiscountPercent()) + .eqIfPresent(ContractDO::getProductPrice, reqVO.getProductPrice()) + .orderByDesc(ContractDO::getId)); + } + + default List selectList(ContractExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(ContractDO::getName, reqVO.getName()) + .eqIfPresent(ContractDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ContractDO::getBusinessId, reqVO.getBusinessId()) + .betweenIfPresent(ContractDO::getOrderDate, reqVO.getOrderDate()) + .eqIfPresent(ContractDO::getNo, reqVO.getNo()) + .eqIfPresent(ContractDO::getDiscountPercent, reqVO.getDiscountPercent()) + .eqIfPresent(ContractDO::getProductPrice, reqVO.getProductPrice()) + .orderByDesc(ContractDO::getId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/package-info.java new file mode 100644 index 000000000..fb8045878 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/package-info.java @@ -0,0 +1,4 @@ +/** + * 合同 + */ +package cn.iocoder.yudao.module.crm.dal.mysql.contract; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java new file mode 100644 index 000000000..0b2497a7b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.customer; + +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.crm.controller.admin.customer.vo.CrmCustomerExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 客户 Mapper + * + * @author Wanwan + */ +@Mapper +public interface CrmCustomerMapper extends BaseMapperX { + + default PageResult selectPage(CrmCustomerPageReqVO reqVO) { + // TODO @Wanwan 填充负责人,所属部门字段;这个可以在 controller 填哈; + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(CrmCustomerDO::getName, reqVO.getName()) + .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile()) + .orderByDesc(CrmCustomerDO::getId)); + } + + default List selectList(CrmCustomerExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(CrmCustomerDO::getName, reqVO.getName()) + .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile()) + .orderByDesc(CrmCustomerDO::getId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/package-info.java new file mode 100644 index 000000000..4173c0180 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/package-info.java @@ -0,0 +1,4 @@ +/** + * 客户 + */ +package cn.iocoder.yudao.module.crm.dal.mysql.customer; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java new file mode 100644 index 000000000..53809f3eb --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.permission; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * crm 数据权限 mapper + * + * @author HUIHUI + */ +@Mapper +public interface CrmPermissionMapper extends BaseMapperX { + + default CrmPermissionDO selectByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId) { + return selectOne(new LambdaQueryWrapperX() + .eq(CrmPermissionDO::getCrmType, crmType).eq(CrmPermissionDO::getCrmDataId, crmDataId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/package-info.java new file mode 100644 index 000000000..ff0e16b90 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.permission; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/package-info.java new file mode 100644 index 000000000..be0fa00a9 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/package-info.java @@ -0,0 +1,4 @@ +/** + * 产品表 + */ +package cn.iocoder.yudao.module.crm.dal.mysql.product; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/ReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/ReceivableMapper.java new file mode 100644 index 000000000..08031772c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/ReceivableMapper.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.receivable; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivableDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.*; + +/** + * 回款管理 Mapper + * + * @author 赤焰 + */ +@Mapper +public interface ReceivableMapper extends BaseMapperX { + + default PageResult selectPage(ReceivablePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ReceivableDO::getNo, reqVO.getNo()) + .eqIfPresent(ReceivableDO::getPlanId, reqVO.getPlanId()) + .eqIfPresent(ReceivableDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ReceivableDO::getContractId, reqVO.getContractId()) + .eqIfPresent(ReceivableDO::getCheckStatus, reqVO.getCheckStatus()) + .eqIfPresent(ReceivableDO::getProcessInstanceId, reqVO.getProcessInstanceId()) + .betweenIfPresent(ReceivableDO::getReturnTime, reqVO.getReturnTime()) + .eqIfPresent(ReceivableDO::getReturnType, reqVO.getReturnType()) + .eqIfPresent(ReceivableDO::getPrice, reqVO.getPrice()) + .eqIfPresent(ReceivableDO::getOwnerUserId, reqVO.getOwnerUserId()) + .eqIfPresent(ReceivableDO::getBatchId, reqVO.getBatchId()) + .eqIfPresent(ReceivableDO::getSort, reqVO.getSort()) + .eqIfPresent(ReceivableDO::getDataScope, reqVO.getDataScope()) + .eqIfPresent(ReceivableDO::getDataScopeDeptIds, reqVO.getDataScopeDeptIds()) + .eqIfPresent(ReceivableDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ReceivableDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(ReceivableDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ReceivableDO::getId)); + } + + default List selectList(ReceivableExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(ReceivableDO::getNo, reqVO.getNo()) + .eqIfPresent(ReceivableDO::getPlanId, reqVO.getPlanId()) + .eqIfPresent(ReceivableDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ReceivableDO::getContractId, reqVO.getContractId()) + .eqIfPresent(ReceivableDO::getCheckStatus, reqVO.getCheckStatus()) + .eqIfPresent(ReceivableDO::getProcessInstanceId, reqVO.getProcessInstanceId()) + .betweenIfPresent(ReceivableDO::getReturnTime, reqVO.getReturnTime()) + .eqIfPresent(ReceivableDO::getReturnType, reqVO.getReturnType()) + .eqIfPresent(ReceivableDO::getPrice, reqVO.getPrice()) + .eqIfPresent(ReceivableDO::getOwnerUserId, reqVO.getOwnerUserId()) + .eqIfPresent(ReceivableDO::getBatchId, reqVO.getBatchId()) + .eqIfPresent(ReceivableDO::getSort, reqVO.getSort()) + .eqIfPresent(ReceivableDO::getDataScope, reqVO.getDataScope()) + .eqIfPresent(ReceivableDO::getDataScopeDeptIds, reqVO.getDataScopeDeptIds()) + .eqIfPresent(ReceivableDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ReceivableDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(ReceivableDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ReceivableDO::getId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/ReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/ReceivablePlanMapper.java new file mode 100644 index 000000000..ac35133a7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/ReceivablePlanMapper.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.receivable; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivablePlanDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.*; + +/** + * 回款计划 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ReceivablePlanMapper extends BaseMapperX { + + default PageResult selectPage(ReceivablePlanPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ReceivablePlanDO::getIndexNo, reqVO.getIndexNo()) + .eqIfPresent(ReceivablePlanDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ReceivablePlanDO::getCheckStatus, reqVO.getCheckStatus()) + .betweenIfPresent(ReceivablePlanDO::getReturnTime, reqVO.getReturnTime()) + .eqIfPresent(ReceivablePlanDO::getRemindDays, reqVO.getRemindDays()) + .betweenIfPresent(ReceivablePlanDO::getRemindTime, reqVO.getRemindTime()) + .eqIfPresent(ReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ReceivablePlanDO::getContractId, reqVO.getContractId()) + .eqIfPresent(ReceivablePlanDO::getOwnerUserId, reqVO.getOwnerUserId()) + .eqIfPresent(ReceivablePlanDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(ReceivablePlanDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ReceivablePlanDO::getId)); + } + + default List selectList(ReceivablePlanExportReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(ReceivablePlanDO::getIndexNo, reqVO.getIndexNo()) + .eqIfPresent(ReceivablePlanDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ReceivablePlanDO::getCheckStatus, reqVO.getCheckStatus()) + .betweenIfPresent(ReceivablePlanDO::getReturnTime, reqVO.getReturnTime()) + .eqIfPresent(ReceivablePlanDO::getRemindDays, reqVO.getRemindDays()) + .betweenIfPresent(ReceivablePlanDO::getRemindTime, reqVO.getRemindTime()) + .eqIfPresent(ReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ReceivablePlanDO::getContractId, reqVO.getContractId()) + .eqIfPresent(ReceivablePlanDO::getOwnerUserId, reqVO.getOwnerUserId()) + .eqIfPresent(ReceivablePlanDO::getRemark, reqVO.getRemark()) + .betweenIfPresent(ReceivablePlanDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ReceivablePlanDO::getId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/package-info.java new file mode 100644 index 000000000..65b30aa92 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/package-info.java @@ -0,0 +1,4 @@ +/** + * 回款 + */ +package cn.iocoder.yudao.module.crm.dal.mysql.receivable; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java new file mode 100644 index 000000000..9d1733b30 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.crm.framework.core.annotations; + +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; + +/** + * Crm 数据操作权限校验 AOP 注解 + * + * @author HUIHUI + */ +@Target({METHOD, ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface CrmPermission { + + /** + * crm 类型 + */ + CrmEnum crmType(); + + /** + * 操作类型 + */ + OperationTypeEnum operationType(); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java new file mode 100644 index 000000000..48d29c6c4 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.crm.framework.core.aop; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_MODEL_NOT_EXISTS; + +/** + * Crm 数据权限校验 AOP 切面 + * + * @author HUIHUI + */ +@Component +@Aspect +@Slf4j +public class CrmPermissionAspect { + + @Resource + private CrmPermissionService crmPermissionService; + + /** + * 获得用户编号 + * + * @return 用户编号 + */ + private static Long getUserId() { + return WebFrameworkUtils.getLoginUserId(); + } + + @Before("@annotation(crmPermission)") + public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) { + try { + Integer crmType = crmPermission.crmType().getType(); + Integer operationType = crmPermission.operationType().getType(); + // TODO @puhui999:不一定是 id 参数噢;例如说,ContactServiceImpl 的 updateContact + Long id = (Long) joinPoint.getArgs()[0];// 获取操作数据的编号 + + // 1.1 获取数据权限 + CrmPermissionDO permission = crmPermissionService.getCrmPermissionByCrmTypeAndCrmDataId(crmType, id); + if (permission == null) { + // 不存在说明数据也不存在 + throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmPermission.crmType().getName()); + } + // 1.2 校验是否为公海数据 + // TODO @puhui999:这个判断去掉比较合适哈。这里更多是业务逻辑,不算权限判断。例如说,公海的客户,只要没负责人,就可以领取了; + if (permission.getOwnerUserId() == null) { + return; + } + // 1.3 校验当前负责人是不是自己 + if (ObjUtil.equal(permission.getOwnerUserId(), getUserId())) { + return; + } + // 1.4 TODO 校验是否为超级管理员 + + // 2. 校验是否有读权限 + if (OperationTypeEnum.isRead(operationType)) { + // 校验该数据当前用户是否可读 + // TODO @puhui999:直接 CollUtil.contains 就好,因为就是有某个 userId 呀 + boolean isRead = CollUtil.contains(permission.getRoUserIds(), item -> ObjUtil.equal(item, getUserId())) + || CollUtil.contains(permission.getRwUserIds(), item -> ObjUtil.equal(item, getUserId())); + if (isRead) { + return; + } + } + + // 3. 校验是否有编辑权限 + if (OperationTypeEnum.isEdit(operationType)) { + // 校验该数据当前用户是否可读写 + if (CollUtil.contains(permission.getRwUserIds(), item -> ObjUtil.equal(item, getUserId()))) { + return; + } + } + + // 4. 没通过结束,报错 {}操作失败,原因:没有权限 + throw exception(CRM_PERMISSION_DENIED, crmPermission.crmType().getName()); + } catch (Exception ex) { + log.error("[doBefore][crmPermission({}) 数据校验错误]", toJsonString(crmPermission), ex); + } + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java new file mode 100644 index 000000000..4a3e65722 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.framework.core; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmEnum.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmEnum.java new file mode 100644 index 000000000..eb6110ec0 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/CrmEnum.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.crm.framework.enums; + +import cn.hutool.core.util.ObjUtil; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +// TODO @puhui999:可以改成 CrmBizTypeEnum,CRM 业务类型枚举 +/** + * Crm 类型枚举 + * + * @author HUIHUI + */ +@RequiredArgsConstructor +@Getter +public enum CrmEnum { + + CRM_LEADS(1, "线索"), + CRM_CUSTOMER(2, "客户"), + CRM_CONTACTS(3, "联系人"), + CRM_BUSINESS(5, "商机"), + CRM_CONTRACT(6, "合同"); + + /** + * 类型 + */ + private final Integer type; + /** + * 名称 + */ + private final String name; + + public static String getNameByType(Integer type) { + for (CrmEnum crmEnum : CrmEnum.values()) { + if (ObjUtil.equal(crmEnum.type, type)) { + return crmEnum.name; + } + } + return ""; + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/OperationTypeEnum.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/OperationTypeEnum.java new file mode 100644 index 000000000..893717154 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/enums/OperationTypeEnum.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.crm.framework.enums; + +import cn.hutool.core.util.ObjUtil; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +// TODO @puhui999:是不是可以和 PermissionTypeEnum 合并,就是 CrmPermissionEnum,负责人、读取、读写;目前阶段,不用做的特别细致;类似 linux 的 acl; +/** + * Crm 数据操作类型枚举 + * + * @author HUIHUI + */ +@RequiredArgsConstructor +@Getter +public enum OperationTypeEnum { + + // TODO @puhui999:抽象上,就分三种,会更合理。一个 OWNER 负责人,一个 READ 读,一个 WRITE 写; + DELETE(1, "删除"), + UPDATE(2, "修改"), + READ(3, "查询"); + + /** + * 类型 + */ + private final Integer type; + + /** + * 名称 + */ + private final String name; + + public static boolean isRead(Integer type) { + return ObjUtil.equal(type, READ.getType()); + } + + public static boolean isEdit(Integer type) { + return ObjUtil.equal(type, UPDATE.getType()) || ObjUtil.equal(type, DELETE.getType()); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/package-info.java new file mode 100644 index 000000000..281e36c45 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 crm 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.crm.framework; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/package-info.java new file mode 100644 index 000000000..2ea5f9f41 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/package-info.java @@ -0,0 +1,10 @@ +/** + * crm 包下,客户关系管理(Customer Relationship Management)。 + * 例如说:客户、联系人、商机、合同、回款等等 + * + * 1. Controller URL:以 /crm/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 crm_ 开头,方便在数据库中区分 + * + * 注意,由于 Crm 模块下,容易和其它模块重名,所以类名都加载 Crm 的前缀~ + */ +package cn.iocoder.yudao.module.crm; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java new file mode 100644 index 000000000..63baad383 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.crm.service.business; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 商机 Service 接口 + * + * @author ljlleo + */ +public interface CrmBusinessService { + + /** + * 创建商机 + * + * @param createReqVO 创建信息 + * @param userId 用户编号 + * @return 编号 + */ + Long createBusiness(@Valid CrmBusinessCreateReqVO createReqVO, Long userId); + + /** + * 更新商机 + * + * @param updateReqVO 更新信息 + */ + void updateBusiness(@Valid CrmBusinessUpdateReqVO updateReqVO); + + /** + * 删除商机 + * + * @param id 编号 + */ + void deleteBusiness(Long id); + + /** + * 获得商机 + * + * @param id 编号 + * @return 商机 + */ + CrmBusinessDO getBusiness(Long id); + + /** + * 获得商机列表 + * + * @param ids 编号 + * @return 商机列表 + */ + List getBusinessList(Collection ids); + + /** + * 获得商机分页 + * + * @param pageReqVO 分页查询 + * @return 商机分页 + */ + PageResult getBusinessPage(CrmBusinessPageReqVO pageReqVO); + + /** + * 获得商机列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 商机列表 + */ + List getBusinessList(CrmBusinessExportReqVO exportReqVO); + + /** + * 商机转移 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferBusiness(CrmTransferBusinessReqVO reqVO, Long userId); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java new file mode 100644 index 000000000..2885e862d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -0,0 +1,121 @@ +package cn.iocoder.yudao.module.crm.service.business; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.*; +import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; +import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; + +/** + * 商机 Service 实现类 + * + * @author ljlleo + */ +@Service +@Validated +public class CrmBusinessServiceImpl implements CrmBusinessService { + + @Resource + private CrmBusinessMapper businessMapper; + + @Resource + private CrmPermissionService crmPermissionService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createBusiness(CrmBusinessCreateReqVO createReqVO, Long userId) { + // 插入 + CrmBusinessDO business = CrmBusinessConvert.INSTANCE.convert(createReqVO); + businessMapper.insert(business); + + // 创建数据权限 + crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_BUSINESS.getType()) + .setCrmDataId(business.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人 + + // 返回 + return business.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.UPDATE) + public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) { + // 校验存在 + validateBusinessExists(updateReqVO.getId()); + // 更新 + CrmBusinessDO updateObj = CrmBusinessConvert.INSTANCE.convert(updateReqVO); + businessMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.DELETE) + public void deleteBusiness(Long id) { + // 校验存在 + validateBusinessExists(id); + // 删除 + businessMapper.deleteById(id); + } + + private CrmBusinessDO validateBusinessExists(Long id) { + CrmBusinessDO crmBusiness = businessMapper.selectById(id); + if (crmBusiness == null) { + throw exception(BUSINESS_NOT_EXISTS); + } + return crmBusiness; + } + + @Override + @CrmPermission(crmType = CrmEnum.CRM_BUSINESS, operationType = OperationTypeEnum.READ) + public CrmBusinessDO getBusiness(Long id) { + return businessMapper.selectById(id); + } + + @Override + public List getBusinessList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return businessMapper.selectBatchIds(ids); + } + + @Override + public PageResult getBusinessPage(CrmBusinessPageReqVO pageReqVO) { + return businessMapper.selectPage(pageReqVO); + } + + @Override + public List getBusinessList(CrmBusinessExportReqVO exportReqVO) { + return businessMapper.selectList(exportReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void transferBusiness(CrmTransferBusinessReqVO reqVO, Long userId) { + // 1 校验商机是否存在 + validateBusinessExists(reqVO.getId()); + + // 2. 数据权限转移 + crmPermissionService.transferCrmPermission( + CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_BUSINESS.getType())); + + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/package-info.java new file mode 100644 index 000000000..8995e1242 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/package-info.java @@ -0,0 +1,4 @@ +/** + * 商机(销售机会) + */ +package cn.iocoder.yudao.module.crm.service.business; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusService.java new file mode 100644 index 000000000..44b3e9f1b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusService.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.crm.service.businessstatus; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 商机状态 Service 接口 + * + * @author ljlleo + */ +public interface CrmBusinessStatusService { + + /** + * 创建商机状态 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createBusinessStatus(@Valid CrmBusinessStatusCreateReqVO createReqVO); + + /** + * 更新商机状态 + * + * @param updateReqVO 更新信息 + */ + void updateBusinessStatus(@Valid CrmBusinessStatusUpdateReqVO updateReqVO); + + /** + * 删除商机状态 + * + * @param id 编号 + */ + void deleteBusinessStatus(Long id); + + /** + * 获得商机状态 + * + * @param id 编号 + * @return 商机状态 + */ + CrmBusinessStatusDO getBusinessStatus(Long id); + + /** + * 获得商机状态列表 + * + * @param ids 编号 + * @return 商机状态列表 + */ + List getBusinessStatusList(Collection ids); + + /** + * 获得商机状态分页 + * + * @param pageReqVO 分页查询 + * @return 商机状态分页 + */ + PageResult getBusinessStatusPage(CrmBusinessStatusPageReqVO pageReqVO); + + /** + * 获得商机状态列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 商机状态列表 + */ + List getBusinessStatusList(CrmBusinessStatusExportReqVO exportReqVO); + + /** + * 根据类型 ID 获得商机状态列表 + * + * @param typeId 商机状态类型 ID + * @return 商机状态列表 + */ + List getBusinessStatusListByTypeId(Integer typeId); + + /** + * 获得商机状态列表 + * + * @return 商机状态列表 + */ + List getBusinessStatusList(); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusServiceImpl.java new file mode 100644 index 000000000..e927fac74 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusServiceImpl.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.module.crm.service.businessstatus; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusUpdateReqVO; +import cn.iocoder.yudao.module.crm.convert.businessstatus.CrmBusinessStatusConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO; +import cn.iocoder.yudao.module.crm.dal.mysql.businessstatus.CrmBusinessStatusMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_NOT_EXISTS; + +/** + * 商机状态 Service 实现类 + * + * @author ljlleo + */ +@Service +@Validated +public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { + + @Resource + private CrmBusinessStatusMapper businessStatusMapper; + + @Override + public Long createBusinessStatus(CrmBusinessStatusCreateReqVO createReqVO) { + // 插入 + CrmBusinessStatusDO businessStatus = CrmBusinessStatusConvert.INSTANCE.convert(createReqVO); + businessStatusMapper.insert(businessStatus); + // 返回 + return businessStatus.getId(); + } + + @Override + public void updateBusinessStatus(CrmBusinessStatusUpdateReqVO updateReqVO) { + // 校验存在 + validateBusinessStatusExists(updateReqVO.getId()); + // 更新 + CrmBusinessStatusDO updateObj = CrmBusinessStatusConvert.INSTANCE.convert(updateReqVO); + businessStatusMapper.updateById(updateObj); + } + + @Override + public void deleteBusinessStatus(Long id) { + // 校验存在 + validateBusinessStatusExists(id); + // 删除 + businessStatusMapper.deleteById(id); + } + + private void validateBusinessStatusExists(Long id) { + if (businessStatusMapper.selectById(id) == null) { + throw exception(BUSINESS_STATUS_NOT_EXISTS); + } + } + + @Override + public CrmBusinessStatusDO getBusinessStatus(Long id) { + return businessStatusMapper.selectById(id); + } + + @Override + public List getBusinessStatusList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return businessStatusMapper.selectBatchIds(ids); + } + + @Override + public PageResult getBusinessStatusPage(CrmBusinessStatusPageReqVO pageReqVO) { + return businessStatusMapper.selectPage(pageReqVO); + } + + @Override + public List getBusinessStatusList(CrmBusinessStatusExportReqVO exportReqVO) { + return businessStatusMapper.selectList(exportReqVO); + } + + @Override + public List getBusinessStatusListByTypeId(Integer typeId) { + return businessStatusMapper.getBusinessStatusListByTypeId(typeId); + } + + @Override + public List getBusinessStatusList() { + return businessStatusMapper.selectList(); + } +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeService.java new file mode 100644 index 000000000..3c473f62b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeService.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.crm.service.businessstatustype; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 商机状态类型 Service 接口 + * + * @author ljlleo + */ +public interface CrmBusinessStatusTypeService { + + /** + * 创建商机状态类型 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createBusinessStatusType(@Valid CrmBusinessStatusTypeCreateReqVO createReqVO); + + /** + * 更新商机状态类型 + * + * @param updateReqVO 更新信息 + */ + void updateBusinessStatusType(@Valid CrmBusinessStatusTypeUpdateReqVO updateReqVO); + + /** + * 删除商机状态类型 + * + * @param id 编号 + */ + void deleteBusinessStatusType(Long id); + + /** + * 获得商机状态类型 + * + * @param id 编号 + * @return 商机状态类型 + */ + CrmBusinessStatusTypeDO getBusinessStatusType(Long id); + + /** + * 获得商机状态类型列表 + * + * @param ids 编号 + * @return 商机状态类型列表 + */ + List getBusinessStatusTypeList(Collection ids); + + /** + * 获得商机状态类型分页 + * + * @param pageReqVO 分页查询 + * @return 商机状态类型分页 + */ + PageResult getBusinessStatusTypePage(CrmBusinessStatusTypePageReqVO pageReqVO); + + /** + * 获得商机状态类型列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 商机状态类型列表 + */ + List getBusinessStatusTypeList(CrmBusinessStatusTypeExportReqVO exportReqVO); + + /** + * 获得商机状态类型列表 + * + * @param status 状态 + * @return 商机状态类型列表 + */ + List getBusinessStatusTypeListByStatus(Integer status); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeServiceImpl.java new file mode 100644 index 000000000..f428c3836 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeServiceImpl.java @@ -0,0 +1,98 @@ +package cn.iocoder.yudao.module.crm.service.businessstatustype; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeUpdateReqVO; +import cn.iocoder.yudao.module.crm.convert.businessstatustype.CrmBusinessStatusTypeConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO; +import cn.iocoder.yudao.module.crm.dal.mysql.businessstatustype.CrmBusinessStatusTypeMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_EXISTS; + +/** + * 商机状态类型 Service 实现类 + * + * @author ljlleo + */ +@Service +@Validated +public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeService { + + @Resource + private CrmBusinessStatusTypeMapper businessStatusTypeMapper; + + @Override + public Long createBusinessStatusType(CrmBusinessStatusTypeCreateReqVO createReqVO) { + // TODO ljlleo:name 应该需要唯一哈; + // 插入 + CrmBusinessStatusTypeDO businessStatusType = CrmBusinessStatusTypeConvert.INSTANCE.convert(createReqVO); + businessStatusTypeMapper.insert(businessStatusType); + // 返回 + return businessStatusType.getId(); + } + + @Override + public void updateBusinessStatusType(CrmBusinessStatusTypeUpdateReqVO updateReqVO) { + // TODO ljlleo:name 应该需要唯一哈; + // 校验存在 + validateBusinessStatusTypeExists(updateReqVO.getId()); + // 更新 + CrmBusinessStatusTypeDO updateObj = CrmBusinessStatusTypeConvert.INSTANCE.convert(updateReqVO); + businessStatusTypeMapper.updateById(updateObj); + } + + @Override + public void deleteBusinessStatusType(Long id) { + // 校验存在 + validateBusinessStatusTypeExists(id); + // TODO 艿艿:这里在看看,是不是要校验业务是否在使用; + // 删除 + businessStatusTypeMapper.deleteById(id); + } + + private void validateBusinessStatusTypeExists(Long id) { + if (businessStatusTypeMapper.selectById(id) == null) { + throw exception(BUSINESS_STATUS_TYPE_NOT_EXISTS); + } + } + + @Override + public CrmBusinessStatusTypeDO getBusinessStatusType(Long id) { + return businessStatusTypeMapper.selectById(id); + } + + @Override + public List getBusinessStatusTypeList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return businessStatusTypeMapper.selectBatchIds(ids); + } + + @Override + public PageResult getBusinessStatusTypePage(CrmBusinessStatusTypePageReqVO pageReqVO) { + return businessStatusTypeMapper.selectPage(pageReqVO); + } + + @Override + public List getBusinessStatusTypeList(CrmBusinessStatusTypeExportReqVO exportReqVO) { + return businessStatusTypeMapper.selectList(exportReqVO); + } + + @Override + public List getBusinessStatusTypeListByStatus(Integer status) { + return businessStatusTypeMapper.getBusinessStatusTypeListByStatus(status); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java new file mode 100644 index 000000000..3bf627f5f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.crm.service.clue; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * 线索 Service 接口 + * + * @author Wanwan + */ +public interface CrmClueService { + + /** + * 创建线索 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createClue(@Valid CrmClueCreateReqVO createReqVO); + + /** + * 更新线索 + * + * @param updateReqVO 更新信息 + */ + void updateClue(@Valid CrmClueUpdateReqVO updateReqVO); + + /** + * 删除线索 + * + * @param id 编号 + */ + void deleteClue(Long id); + + /** + * 获得线索 + * + * @param id 编号 + * @return 线索 + */ + CrmClueDO getClue(Long id); + + /** + * 获得线索列表 + * + * @param ids 编号 + * @return 线索列表 + */ + List getClueList(Collection ids); + + /** + * 获得线索分页 + * + * @param pageReqVO 分页查询 + * @return 线索分页 + */ + PageResult getCluePage(CrmCluePageReqVO pageReqVO); + + /** + * 获得线索列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 线索列表 + */ + List getClueList(CrmClueExportReqVO exportReqVO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java new file mode 100644 index 000000000..362637e30 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.module.crm.service.clue; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; +import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.CLUE_NOT_EXISTS; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; + +/** + * 线索 Service 实现类 + * + * @author Wanwan + */ +@Service +@Validated +public class CrmClueServiceImpl implements CrmClueService { + + @Resource + private CrmClueMapper clueMapper; + @Resource + private CrmCustomerService customerService; + + @Override + public Long createClue(CrmClueCreateReqVO createReqVO) { + // 校验客户是否存在 + customerService.validateCustomer(createReqVO.getCustomerId()); + // 插入 + CrmClueDO clue = CrmClueConvert.INSTANCE.convert(createReqVO); + clueMapper.insert(clue); + // 返回 + return clue.getId(); + } + + @Override + public void updateClue(CrmClueUpdateReqVO updateReqVO) { + // 校验存在 + validateClueExists(updateReqVO.getId()); + // 校验客户是否存在 + customerService.validateCustomer(updateReqVO.getCustomerId()); + + // 更新 + CrmClueDO updateObj = CrmClueConvert.INSTANCE.convert(updateReqVO); + clueMapper.updateById(updateObj); + } + + @Override + public void deleteClue(Long id) { + // 校验存在 + validateClueExists(id); + // 删除 + clueMapper.deleteById(id); + } + + private void validateClueExists(Long id) { + if (clueMapper.selectById(id) == null) { + throw exception(CLUE_NOT_EXISTS); + } + } + + @Override + public CrmClueDO getClue(Long id) { + return clueMapper.selectById(id); + } + + @Override + public List getClueList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return clueMapper.selectBatchIds(ids); + } + + @Override + public PageResult getCluePage(CrmCluePageReqVO pageReqVO) { + return clueMapper.selectPage(pageReqVO); + } + + @Override + public List getClueList(CrmClueExportReqVO exportReqVO) { + return clueMapper.selectList(exportReqVO); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/package-info.java new file mode 100644 index 000000000..5cb8b6ec7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/package-info.java @@ -0,0 +1,4 @@ +/** + * 线索 + */ +package cn.iocoder.yudao.module.crm.service.clue; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactService.java new file mode 100644 index 000000000..6da77138e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactService.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.crm.service.contact; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * crm联系人 Service 接口 + * + * @author 芋道源码 + */ +public interface ContactService { + + /** + * 创建crm联系人 + * + * @param createReqVO 创建信息 + * @param userId 用户编号 + * @return 编号 + */ + Long createContact(@Valid ContactCreateReqVO createReqVO, Long userId); + + /** + * 更新crm联系人 + * + * @param updateReqVO 更新信息 + */ + void updateContact(@Valid ContactUpdateReqVO updateReqVO); + + /** + * 删除crm联系人 + * + * @param id 编号 + */ + void deleteContact(Long id); + + /** + * 获得crm联系人 + * + * @param id 编号 + * @return crm联系人 + */ + ContactDO getContact(Long id); + + /** + * 获得crm联系人列表 + * + * @param ids 编号 + * @return crm联系人列表 + */ + List getContactList(Collection ids); + + /** + * 获得crm联系人分页 + * + * @param pageReqVO 分页查询 + * @return crm联系人分页 + */ + PageResult getContactPage(ContactPageReqVO pageReqVO); + + /** + * 获得crm联系人列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return crm联系人列表 + */ + List getContactList(ContactExportReqVO exportReqVO); + + /** + * 联系人编号 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferContact(CrmTransferContactReqVO reqVO, Long userId); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactServiceImpl.java new file mode 100644 index 000000000..aea47ecb4 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/ContactServiceImpl.java @@ -0,0 +1,122 @@ +package cn.iocoder.yudao.module.crm.service.contact; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; +import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.ContactDO; +import cn.iocoder.yudao.module.crm.dal.mysql.contact.ContactMapper; +import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.CONTACT_NOT_EXISTS; + +/** + * crm联系人 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ContactServiceImpl implements ContactService { + + @Resource + private ContactMapper contactMapper; + + @Resource + private CrmPermissionService crmPermissionService; + + @Override + public Long createContact(ContactCreateReqVO createReqVO, Long userId) { + // TODO @customerId:需要校验存在 + // 插入 + ContactDO contact = ContactConvert.INSTANCE.convert(createReqVO); + contactMapper.insert(contact); + + // 创建数据权限 + crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_BUSINESS.getType()) + .setCrmDataId(contact.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人 + + // 返回 + return contact.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.UPDATE) + public void updateContact(ContactUpdateReqVO updateReqVO) { + // 校验存在 + validateContactExists(updateReqVO.getId()); + // TODO @customerId:需要校验存在 + + // 更新 + ContactDO updateObj = ContactConvert.INSTANCE.convert(updateReqVO); + contactMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.DELETE) + public void deleteContact(Long id) { + // 校验存在 + validateContactExists(id); + // 删除 + contactMapper.deleteById(id); + } + + private ContactDO validateContactExists(Long id) { + ContactDO contact = contactMapper.selectById(id); + if (contact == null) { + throw exception(CONTACT_NOT_EXISTS); + } + return contact; + } + + @Override + @CrmPermission(crmType = CrmEnum.CRM_CONTACTS, operationType = OperationTypeEnum.READ) + public ContactDO getContact(Long id) { + return contactMapper.selectById(id); + } + + @Override + public List getContactList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return contactMapper.selectBatchIds(ids); + } + + @Override + public PageResult getContactPage(ContactPageReqVO pageReqVO) { + return contactMapper.selectPage(pageReqVO); + } + + @Override + public List getContactList(ContactExportReqVO exportReqVO) { + return contactMapper.selectList(exportReqVO); + } + + @Override + public void transferContact(CrmTransferContactReqVO reqVO, Long userId) { + // 1 校验联系人是否存在 + validateContactExists(reqVO.getId()); + + // 2. 数据权限转移 + crmPermissionService.transferCrmPermission( + ContactConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CONTACTS.getType())); + + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/package-info.java new file mode 100644 index 000000000..e72077dd7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/package-info.java @@ -0,0 +1,4 @@ +/** + * 联系人 + */ +package cn.iocoder.yudao.module.crm.service.contact; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractService.java new file mode 100644 index 000000000..8cf41c152 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractService.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.crm.service.contract; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 合同 Service 接口 + * + * @author dhb52 + */ +public interface ContractService { + + /** + * 创建合同 + * + * @param createReqVO 创建信息 + * @param userId 用户编号 + * @return 编号 + */ + Long createContract(@Valid ContractCreateReqVO createReqVO, Long userId); + + /** + * 更新合同 + * + * @param updateReqVO 更新信息 + */ + void updateContract(@Valid ContractUpdateReqVO updateReqVO); + + /** + * 删除合同 + * + * @param id 编号 + */ + void deleteContract(Long id); + + /** + * 获得合同 + * + * @param id 编号 + * @return 合同 + */ + ContractDO getContract(Long id); + + /** + * 获得合同列表 + * + * @param ids 编号 + * @return 合同列表 + */ + List getContractList(Collection ids); + + /** + * 获得合同分页 + * + * @param pageReqVO 分页查询 + * @return 合同分页 + */ + PageResult getContractPage(ContractPageReqVO pageReqVO); + + /** + * 获得合同列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 合同列表 + */ + List getContractList(ContractExportReqVO exportReqVO); + + /** + * 合同转移 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferContract(CrmTransferContractReqVO reqVO, Long userId); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImpl.java new file mode 100644 index 000000000..fa3940f6a --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImpl.java @@ -0,0 +1,120 @@ +package cn.iocoder.yudao.module.crm.service.contract; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO; +import cn.iocoder.yudao.module.crm.dal.mysql.contract.ContractMapper; +import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS; + +/** + * 合同 Service 实现类 + * + * @author dhb52 + */ +@Service +@Validated +public class ContractServiceImpl implements ContractService { + + @Resource + private ContractMapper contractMapper; + + @Resource + private CrmPermissionService crmPermissionService; + + @Override + public Long createContract(ContractCreateReqVO createReqVO, Long userId) { + // 插入 + ContractDO contract = ContractConvert.INSTANCE.convert(createReqVO); + contractMapper.insert(contract); + + // 创建数据权限 + crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_CONTRACT.getType()) + .setCrmDataId(contract.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人 + + // 返回 + return contract.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.DELETE) + public void updateContract(ContractUpdateReqVO updateReqVO) { + // 校验存在 + validateContractExists(updateReqVO.getId()); + // 更新 + ContractDO updateObj = ContractConvert.INSTANCE.convert(updateReqVO); + contractMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.DELETE) + public void deleteContract(Long id) { + // 校验存在 + validateContractExists(id); + // 删除 + contractMapper.deleteById(id); + } + + private ContractDO validateContractExists(Long id) { + ContractDO contract = contractMapper.selectById(id); + if (contract == null) { + throw exception(CONTRACT_NOT_EXISTS); + } + return contract; + } + + @Override + @CrmPermission(crmType = CrmEnum.CRM_CONTRACT, operationType = OperationTypeEnum.READ) + public ContractDO getContract(Long id) { + return contractMapper.selectById(id); + } + + @Override + public List getContractList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return contractMapper.selectBatchIds(ids); + } + + @Override + public PageResult getContractPage(ContractPageReqVO pageReqVO) { + return contractMapper.selectPage(pageReqVO); + } + + @Override + public List getContractList(ContractExportReqVO exportReqVO) { + return contractMapper.selectList(exportReqVO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void transferContract(CrmTransferContractReqVO reqVO, Long userId) { + // 1 校验合同是否存在 + validateContractExists(reqVO.getId()); + + // 2. 数据权限转移 + crmPermissionService.transferCrmPermission( + ContractConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CONTRACT.getType())); + + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/package-info.java new file mode 100644 index 000000000..743f159b7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/package-info.java @@ -0,0 +1,4 @@ +/** + * 合同 + */ +package cn.iocoder.yudao.module.crm.service.contract; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java new file mode 100644 index 000000000..576a9bcbc --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.crm.service.customer; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; + +/** + * 客户 Service 接口 + * + * @author Wanwan + */ +public interface CrmCustomerService { + + /** + * 创建客户 + * + * @param createReqVO 创建信息 + * @param userId 用户编号 + * @return 编号 + */ + Long createCustomer(@Valid CrmCustomerCreateReqVO createReqVO, Long userId); + + /** + * 更新客户 + * + * @param updateReqVO 更新信息 + */ + void updateCustomer(@Valid CrmCustomerUpdateReqVO updateReqVO); + + /** + * 删除客户 + * + * @param id 编号 + */ + void deleteCustomer(Long id); + + /** + * 获得客户 + * + * @param id 编号 + * @return 客户 + */ + CrmCustomerDO getCustomer(Long id); + + /** + * 获得客户列表 + * + * @param ids 编号 + * @return 客户列表 + */ + List getCustomerList(Collection ids); + + /** + * 获得客户分页 + * + * @param pageReqVO 分页查询 + * @return 客户分页 + */ + PageResult getCustomerPage(CrmCustomerPageReqVO pageReqVO); + + /** + * 获得客户列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 客户列表 + */ + List getCustomerList(CrmCustomerExportReqVO exportReqVO); + + /** + * 校验客户是否存在 + * + * @param customerId 客户 id + * @return 客户 + */ + CrmCustomerDO validateCustomer(Long customerId); + + /** + * 客户转移 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferCustomer(CrmTransferCustomerReqVO reqVO, Long userId); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java new file mode 100644 index 000000000..e78717b2c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.module.crm.service.customer; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; +import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; +import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import cn.iocoder.yudao.module.crm.framework.enums.OperationTypeEnum; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; + +/** + * 客户 Service 实现类 + * + * @author Wanwan + */ +@Service +@Validated +public class CrmCustomerServiceImpl implements CrmCustomerService { + + @Resource + private CrmCustomerMapper customerMapper; + @Resource + private DeptApi deptApi; // TODO @wanwan:拼接数据,可以放到 controller;所以这里的引入,可以考虑放到 controller 哈; + @Resource + private CrmPermissionService crmPermissionService; + + @Override + public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { + // 插入 + CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO); + customerMapper.insert(customer); + + // 创建数据权限 + crmPermissionService.createCrmPermission(new CrmPermissionCreateBO().setCrmType(CrmEnum.CRM_CUSTOMER.getType()) + .setCrmDataId(customer.getId()).setOwnerUserId(userId)); // 设置当前操作的人为负责人 + + // 返回 + return customer.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.UPDATE) + public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { + // 校验存在 + validateCustomerExists(updateReqVO.getId()); + // TODO 芋艿:数据权限,校验是否可以操作 + + // 更新 + CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); + customerMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.DELETE) + public void deleteCustomer(Long id) { + // 校验存在 + validateCustomerExists(id); + // TODO 芋艿:数据权限,校验是否可以操作 + + // 删除 + customerMapper.deleteById(id); + } + + private void validateCustomerExists(Long id) { + if (customerMapper.selectById(id) == null) { + throw exception(CUSTOMER_NOT_EXISTS); + } + } + + @Override + @CrmPermission(crmType = CrmEnum.CRM_CUSTOMER, operationType = OperationTypeEnum.READ) + public CrmCustomerDO getCustomer(Long id) { + return customerMapper.selectById(id); + } + + @Override + public List getCustomerList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return customerMapper.selectBatchIds(ids); + } + + @Override + public PageResult getCustomerPage(CrmCustomerPageReqVO pageReqVO) { + // TODO 芋艿:数据权限,是否可以查询到; + return customerMapper.selectPage(pageReqVO); + } + + @Override + public List getCustomerList(CrmCustomerExportReqVO exportReqVO) { + return customerMapper.selectList(exportReqVO); + } + + // TODO wanwan:service 接口已经注释,实现类就不需要了。 + /** + * 校验客户是否存在 + * + * @param customerId 客户 id + * @return 客户 + */ + @Override + public CrmCustomerDO validateCustomer(Long customerId) { + CrmCustomerDO customer = getCustomer(customerId); + if (Objects.isNull(customer)) { + throw exception(CUSTOMER_NOT_EXISTS); + } + return customer; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void transferCustomer(CrmTransferCustomerReqVO reqVO, Long userId) { + // 1. 校验合同是否存在 + validateCustomer(reqVO.getId()); + + // 2. 数据权限转移 + crmPermissionService.transferCrmPermission( + CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setCrmType(CrmEnum.CRM_CUSTOMER.getType())); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/package-info.java new file mode 100644 index 000000000..1ae12a3df --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/package-info.java @@ -0,0 +1,4 @@ +/** + * 客户 + */ +package cn.iocoder.yudao.module.crm.service.customer; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java new file mode 100644 index 000000000..3203c06bc --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.crm.service.permission; + + +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateBO; +import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO; + +import javax.validation.Valid; + +/** + * crm 数据权限 Service 接口 + * + * @author HUIHUI + */ +public interface CrmPermissionService { + + // TODO @puhui999:方法名上,不用 Crm + /** + * 创建数据权限 + * + * @param createBO 创建信息 + * @return 编号 + */ + Long createCrmPermission(@Valid CrmPermissionCreateBO createBO); + + /** + * 更新数据权限 + * + * @param updateBO 更新信息 + */ + void updateCrmPermission(@Valid CrmPermissionUpdateBO updateBO); + + /** + * 删除数据权限 + * + * @param id 编号 + */ + void deleteCrmPermission(Long id); + + /** + * 获得数据权限 + * + * @param crmType 数据类型 关联 {@link CrmEnum} + * @param crmDataId 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId() + * @return 数据权限 + */ + CrmPermissionDO getCrmPermissionByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId); + + /** + * 数据权限转移 + * + * @param transferCrmPermissionBO 数据权限转移请求 + */ + void transferCrmPermission(@Valid TransferCrmPermissionBO transferCrmPermissionBO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java new file mode 100644 index 000000000..687de63ca --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.crm.service.permission; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper; +import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum; +import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateBO; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateBO; +import cn.iocoder.yudao.module.crm.service.permission.bo.TransferCrmPermissionBO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; + +/** + * crm 数据权限 Service 接口实现类 + * + * @author HUIHUI + */ +@Service +@Validated +public class CrmPermissionServiceImpl implements CrmPermissionService { + + @Resource + private CrmPermissionMapper crmPermissionMapper; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createCrmPermission(CrmPermissionCreateBO createBO) { + // TODO @puhui999:createDO 改成 permission,保持统一哈; + CrmPermissionDO createDO = CrmPermissionConvert.INSTANCE.convert(createBO); + crmPermissionMapper.insert(createDO); + return createDO.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateCrmPermission(CrmPermissionUpdateBO updateBO) { + validateCrmPermissionExists(updateBO.getId()); + // 更新操作 + CrmPermissionDO updateDO = CrmPermissionConvert.INSTANCE.convert(updateBO); + crmPermissionMapper.updateById(updateDO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteCrmPermission(Long id) { + validateCrmPermissionExists(id); + // 删除 + crmPermissionMapper.deleteById(id); + } + + private void validateCrmPermissionExists(Long id) { + if (crmPermissionMapper.selectById(id) == null) { + throw exception(CRM_PERMISSION_NOT_EXISTS); + } + } + + @Override + public CrmPermissionDO getCrmPermissionByCrmTypeAndCrmDataId(Integer crmType, Long crmDataId) { + return crmPermissionMapper.selectByCrmTypeAndCrmDataId(crmType, crmDataId); + } + + // TODO @puhui999:参数名,是不是 transferReqBO + @Override + public void transferCrmPermission(TransferCrmPermissionBO transferCrmPermissionBO) { + // 1.1 校验商机是否存在 + // TODO puhui999:这里直接调用 crmPermissionMapper 的 selectByCrmTypeAndCrmDataId 方法,会更简洁一点; + CrmPermissionDO permission = getCrmPermissionByCrmTypeAndCrmDataId(transferCrmPermissionBO.getCrmType(), + transferCrmPermissionBO.getCrmDataId()); + String crmName = CrmEnum.getNameByType(transferCrmPermissionBO.getCrmType()); + if (permission == null) { + throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, crmName); + } + // 1.2 校验转移对象是否已经是该负责人 + if (ObjUtil.equal(permission.getOwnerUserId(), permission.getOwnerUserId())) { + // TODO @puhui999:是不是这个错误码不太对。。。 + throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_NOT_EXISTS, crmName); + } + // 1.3 校验新负责人是否存在 + AdminUserRespDTO user = adminUserApi.getUser(permission.getOwnerUserId()); + if (user == null) { + throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, crmName); + } + // TODO 校验是否为超级管理员 || 1.4 + // 1.4 校验是否有写权限 + // TODO puhui999:CollUtil.contains 就够了,不用后面写个表达式; + if (!CollUtil.contains(permission.getRwUserIds(), id -> ObjUtil.equal(id, transferCrmPermissionBO.getUserId()))) { + throw exception(CRM_PERMISSION_DENIED, crmName); + } + + // 2. 权限转移 + CrmPermissionDO updateCrmPermission = new CrmPermissionDO().setId(permission.getId()) + .setOwnerUserId(transferCrmPermissionBO.getOwnerUserId()); + if (ObjUtil.equal(TransferTypeEnum.TEAM.getType(), transferCrmPermissionBO.getTransferType())) { + if (ObjUtil.equal(PermissionTypeEnum.READONLY.getType(), transferCrmPermissionBO.getPermissionType())) { + Set roUserIds = permission.getRoUserIds(); + roUserIds.add(permission.getOwnerUserId()); // 老负责人加入团队有只读权限 + updateCrmPermission.setRoUserIds(roUserIds); + } + if (ObjUtil.equal(PermissionTypeEnum.READ_AND_WRITE.getType(), transferCrmPermissionBO.getPermissionType())) { + Set rwUserIds = permission.getRwUserIds(); + rwUserIds.add(permission.getOwnerUserId()); // 老负责人加入团队有读写权限 + updateCrmPermission.setRoUserIds(rwUserIds); + } + } + crmPermissionMapper.updateById(updateCrmPermission); + + // 3. TODO 记录机转移日志 + // TODO @puhui999:是不是交给业务记录哈; + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateBO.java new file mode 100644 index 000000000..e5dd5d6e9 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateBO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.crm.service.permission.bo; + +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Set; + +// TODO @puhui999:,一个是 Crm 前缀,一个 Req 表示入参 +/** + * crm 数据权限 Create BO + * + * @author HUIHUI + */ +@Data +public class CrmPermissionCreateBO { + + // TODO @puhui999:如果是关联字段,换一行写它的注释;不然看着略乱哈 + + /** + * Crm 类型 关联 {@link CrmEnum} + */ + @NotNull(message = "Crm 类型不能为空") + private Integer crmType; + /** + * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId() + */ + @NotNull(message = "Crm 数据编号不能为空") + private Long crmDataId; + + /** + * 负责人的用户编号 关联 AdminUser#id, null 则为公海数据 + */ + private Long ownerUserId; + /** + * 只读权限的用户编号数组 + */ + private Set roUserIds; + /** + * 读写权限的用户编号数组 + */ + private Set rwUserIds; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateBO.java new file mode 100644 index 000000000..e8544a611 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateBO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.crm.service.permission.bo; + +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.Set; + +// TODO @puhui999:,一个是 Crm 前缀,一个 Req 表示入参 +/** + * crm 数据权限 Update BO + * + * @author HUIHUI + */ +@Data +public class CrmPermissionUpdateBO { + + // TODO @puhui999:id 和 crmType + crmDataId 是不是重叠了; + /** + * 数据权限编号 {@link CrmPermissionDO#getId()} + */ + @NotNull(message = "Crm 数据权限编号不能为空") + private Long id; + + /** + * Crm 类型 关联 {@link CrmEnum} + */ + @NotNull(message = "Crm 类型不能为空") + private Integer crmType; + /** + * 数据编号 关联 {@link CrmEnum} 对应模块 DO#getId() + */ + @NotNull(message = "Crm 数据编号不能为空") + private Long crmDataId; + /** + * 负责人的用户编号 关联 AdminUser#id, null 则为公海数据 + */ + private Long ownerUserId; + /** + * 只读权限的用户编号数组 + */ + private Set roUserIds; + /** + * 读写权限的用户编号数组 + */ + private Set rwUserIds; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/TransferCrmPermissionBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/TransferCrmPermissionBO.java new file mode 100644 index 000000000..246439bcb --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/TransferCrmPermissionBO.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.crm.service.permission.bo; + +import cn.iocoder.yudao.module.crm.enums.common.PermissionTypeEnum; +import cn.iocoder.yudao.module.crm.enums.common.TransferTypeEnum; +import cn.iocoder.yudao.module.crm.framework.enums.CrmEnum; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +// TODO @puhui999:CrmTransferPermissionReqBO,一个是 Crm 前缀,一个 Req 表示入参 +/** + * 数据权限转移 BO + * + * @author HUIHUI + */ +@Data +public class TransferCrmPermissionBO { + + // TODO @puhui999:参数的注释 + @NotNull(message = "用户编号不能为空") + private Long userId; + + // TODO @puhui999:bizType + /** + * Crm 类型 关联 {@link CrmEnum} TODO 这种不用再写关联了,直接 @InEnum 参数校验 + */ + @NotNull(message = "Crm 类型不能为空") + private Integer crmType; + + // TODO @puhui999:bizId + /** + * 数据编号 + */ + @NotNull(message = "Crm 数据编号不能为空") + private Long crmDataId; + + // TODO @puhui999:要不这里改成 newOwnerUserId;然后,transferType 和 permissionType,合并成 oldOwnerPermission(空就是移除) + @NotNull(message = "新负责人的用户编号不能为空") + private Long ownerUserId; + + /** + * 原负责人移除方式, 关联 {@link TransferTypeEnum} TODO 这种不用再写关联了,直接 @InEnum 参数校验 + */ + @NotNull(message = "原负责人移除方式不能为空") + private Integer transferType; + + /** + * 权限类型, 关联 {@link PermissionTypeEnum} + */ + @NotNull(message = "权限类型不能为空") + private Integer permissionType; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/package-info.java new file mode 100644 index 000000000..cae179aea --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/package-info.java @@ -0,0 +1,4 @@ +/** + * 产品表 + */ +package cn.iocoder.yudao.module.crm.service.product; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanService.java new file mode 100644 index 000000000..163ebc26a --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanService.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.crm.service.receivable; + +import java.util.*; +import javax.validation.*; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivablePlanDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * 回款计划 Service 接口 + * + * @author 芋道源码 + */ +public interface ReceivablePlanService { + + /** + * 创建回款计划 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReceivablePlan(@Valid ReceivablePlanCreateReqVO createReqVO); + + /** + * 更新回款计划 + * + * @param updateReqVO 更新信息 + */ + void updateReceivablePlan(@Valid ReceivablePlanUpdateReqVO updateReqVO); + + /** + * 删除回款计划 + * + * @param id 编号 + */ + void deleteReceivablePlan(Long id); + + /** + * 获得回款计划 + * + * @param id 编号 + * @return 回款计划 + */ + ReceivablePlanDO getReceivablePlan(Long id); + + /** + * 获得回款计划列表 + * + * @param ids 编号 + * @return 回款计划列表 + */ + List getReceivablePlanList(Collection ids); + + /** + * 获得回款计划分页 + * + * @param pageReqVO 分页查询 + * @return 回款计划分页 + */ + PageResult getReceivablePlanPage(ReceivablePlanPageReqVO pageReqVO); + + /** + * 获得回款计划列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 回款计划列表 + */ + List getReceivablePlanList(ReceivablePlanExportReqVO exportReqVO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanServiceImpl.java new file mode 100644 index 000000000..c0b236ac0 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanServiceImpl.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.crm.service.receivable; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePlanCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePlanExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePlanPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePlanUpdateReqVO; +import cn.iocoder.yudao.module.crm.convert.receivable.ReceivablePlanConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivablePlanDO; +import cn.iocoder.yudao.module.crm.dal.mysql.receivable.ReceivablePlanMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.RECEIVABLE_PLAN_NOT_EXISTS; + +/** + * 回款计划 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ReceivablePlanServiceImpl implements ReceivablePlanService { + + @Resource + private ReceivablePlanMapper receivablePlanMapper; + + @Override + public Long createReceivablePlan(ReceivablePlanCreateReqVO createReqVO) { + // 插入 + ReceivablePlanDO receivablePlan = ReceivablePlanConvert.INSTANCE.convert(createReqVO); + // TODO @liuhongfeng:空格要注释;if (ObjectUtil.isNull(receivablePlan.getStatus())) { + if(ObjectUtil.isNull(receivablePlan.getStatus())){ + receivablePlan.setStatus(CommonStatusEnum.ENABLE.getStatus()); + } + receivablePlanMapper.insert(receivablePlan); + // 返回 + return receivablePlan.getId(); + } + + @Override + public void updateReceivablePlan(ReceivablePlanUpdateReqVO updateReqVO) { + // 校验存在 + validateReceivablePlanExists(updateReqVO.getId()); + + // 更新 + ReceivablePlanDO updateObj = ReceivablePlanConvert.INSTANCE.convert(updateReqVO); + receivablePlanMapper.updateById(updateObj); + } + + @Override + public void deleteReceivablePlan(Long id) { + // 校验存在 + validateReceivablePlanExists(id); + // 删除 + receivablePlanMapper.deleteById(id); + } + + private void validateReceivablePlanExists(Long id) { + if (receivablePlanMapper.selectById(id) == null) { + throw exception(RECEIVABLE_PLAN_NOT_EXISTS); + } + } + + @Override + public ReceivablePlanDO getReceivablePlan(Long id) { + return receivablePlanMapper.selectById(id); + } + + @Override + public List getReceivablePlanList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return receivablePlanMapper.selectBatchIds(ids); + } + + @Override + public PageResult getReceivablePlanPage(ReceivablePlanPageReqVO pageReqVO) { + return receivablePlanMapper.selectPage(pageReqVO); + } + + @Override + public List getReceivablePlanList(ReceivablePlanExportReqVO exportReqVO) { + return receivablePlanMapper.selectList(exportReqVO); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableService.java new file mode 100644 index 000000000..a673ec99e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableService.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.crm.service.receivable; + +import java.util.*; +import javax.validation.*; + +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.*; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivableDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * 回款管理 Service 接口 + * + * @author 赤焰 + */ +public interface ReceivableService { + + /** + * 创建回款管理 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createReceivable(@Valid ReceivableCreateReqVO createReqVO); + + /** + * 更新回款管理 + * + * @param updateReqVO 更新信息 + */ + void updateReceivable(@Valid ReceivableUpdateReqVO updateReqVO); + + /** + * 删除回款管理 + * + * @param id 编号 + */ + void deleteReceivable(Long id); + + /** + * 获得回款管理 + * + * @param id 编号 + * @return 回款管理 + */ + ReceivableDO getReceivable(Long id); + + /** + * 获得回款管理列表 + * + * @param ids 编号 + * @return 回款管理列表 + */ + List getReceivableList(Collection ids); + + /** + * 获得回款管理分页 + * + * @param pageReqVO 分页查询 + * @return 回款管理分页 + */ + PageResult getReceivablePage(ReceivablePageReqVO pageReqVO); + + /** + * 获得回款管理列表, 用于 Excel 导出 + * + * @param exportReqVO 查询条件 + * @return 回款管理列表 + */ + List getReceivableList(ReceivableExportReqVO exportReqVO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableServiceImpl.java new file mode 100644 index 000000000..94b25f6ed --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableServiceImpl.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.crm.service.receivable; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivableCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivableExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivableUpdateReqVO; +import cn.iocoder.yudao.module.crm.convert.receivable.ReceivableConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivableDO; +import cn.iocoder.yudao.module.crm.dal.mysql.receivable.ReceivableMapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +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.crm.enums.ErrorCodeConstants.RECEIVABLE_NOT_EXISTS; + +/** + * 回款管理 Service 实现类 + * + * @author 赤焰 + */ +@Service +@Validated +public class ReceivableServiceImpl implements ReceivableService { + + @Resource + private ReceivableMapper receivableMapper; + + @Override + public Long createReceivable(ReceivableCreateReqVO createReqVO) { + // TODO @liuhongfeng:planId 是否存在,是否合法,需要去校验; + // TODO @liuhongfeng:其它类似 customerId、contractId 也需要去校验; + // 插入 + ReceivableDO receivable = ReceivableConvert.INSTANCE.convert(createReqVO); + receivableMapper.insert(receivable); + // 返回 + return receivable.getId(); + } + + @Override + public void updateReceivable(ReceivableUpdateReqVO updateReqVO) { + // 校验存在 + validateReceivableExists(updateReqVO.getId()); + + // 更新 + ReceivableDO updateObj = ReceivableConvert.INSTANCE.convert(updateReqVO); + receivableMapper.updateById(updateObj); + } + + @Override + public void deleteReceivable(Long id) { + // 校验存在 + validateReceivableExists(id); + // 删除 + receivableMapper.deleteById(id); + } + + private void validateReceivableExists(Long id) { + if (receivableMapper.selectById(id) == null) { + throw exception(RECEIVABLE_NOT_EXISTS); + } + } + + @Override + public ReceivableDO getReceivable(Long id) { + return receivableMapper.selectById(id); + } + + @Override + public List getReceivableList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return receivableMapper.selectBatchIds(ids); + } + + @Override + public PageResult getReceivablePage(ReceivablePageReqVO pageReqVO) { + return receivableMapper.selectPage(pageReqVO); + } + + @Override + public List getReceivableList(ReceivableExportReqVO exportReqVO) { + return receivableMapper.selectList(exportReqVO); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/package-info.java new file mode 100644 index 000000000..4004b301d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/package-info.java @@ -0,0 +1,4 @@ +/** + * 回款 + */ +package cn.iocoder.yudao.module.crm.service.receivable; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/business/CrmBusinessMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/business/CrmBusinessMapper.xml new file mode 100644 index 000000000..c35aafec7 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/business/CrmBusinessMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/businessstatustype/CrmBusinessStatusTypeMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/businessstatustype/CrmBusinessStatusTypeMapper.xml new file mode 100644 index 000000000..44fbd07ec --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/businessstatustype/CrmBusinessStatusTypeMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/clue/CrmClueMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/clue/CrmClueMapper.xml new file mode 100644 index 000000000..3f15cf766 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/clue/CrmClueMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/contact/ContactMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/contact/ContactMapper.xml new file mode 100644 index 000000000..e2c69ca78 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/contact/ContactMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/customer/CrmCustomerMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/customer/CrmCustomerMapper.xml new file mode 100644 index 000000000..85eb90d07 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/customer/CrmCustomerMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/receivable/ReceivableMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/receivable/ReceivableMapper.xml new file mode 100644 index 000000000..b87beb08f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/receivable/ReceivableMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/receivable/ReceivablePlanMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/receivable/ReceivablePlanMapper.xml new file mode 100644 index 000000000..f0e4c2e84 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/receivable/ReceivablePlanMapper.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java new file mode 100644 index 000000000..9f199954e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImplTest.java @@ -0,0 +1,264 @@ +package cn.iocoder.yudao.module.crm.service.business; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.CrmBusinessCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.CrmBusinessExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.CrmBusinessUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +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.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link CrmBusinessServiceImpl} 的单元测试类 + * + * @author ljlleo + */ +@Import(CrmBusinessServiceImpl.class) +public class CrmBusinessServiceImplTest extends BaseDbUnitTest { + + @Resource + private CrmBusinessServiceImpl businessService; + + @Resource + private CrmBusinessMapper businessMapper; + + @Test + public void testCreateBusiness_success() { + // 准备参数 + CrmBusinessCreateReqVO reqVO = randomPojo(CrmBusinessCreateReqVO.class); + + // 调用 + Long businessId = businessService.createBusiness(reqVO, getLoginUserId()); + // 断言 + assertNotNull(businessId); + // 校验记录的属性是否正确 + CrmBusinessDO business = businessMapper.selectById(businessId); + assertPojoEquals(reqVO, business); + } + + @Test + public void testUpdateBusiness_success() { + // mock 数据 + CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class); + businessMapper.insert(dbBusiness);// @Sql: 先插入出一条存在的数据 + // 准备参数 + CrmBusinessUpdateReqVO reqVO = randomPojo(CrmBusinessUpdateReqVO.class, o -> { + o.setId(dbBusiness.getId()); // 设置更新的 ID + }); + + // 调用 + businessService.updateBusiness(reqVO); + // 校验是否更新正确 + CrmBusinessDO business = businessMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, business); + } + + @Test + public void testUpdateBusiness_notExists() { + // 准备参数 + CrmBusinessUpdateReqVO reqVO = randomPojo(CrmBusinessUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> businessService.updateBusiness(reqVO), BUSINESS_NOT_EXISTS); + } + + @Test + public void testDeleteBusiness_success() { + // mock 数据 + CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class); + businessMapper.insert(dbBusiness);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbBusiness.getId(); + + // 调用 + businessService.deleteBusiness(id); + // 校验数据不存在了 + assertNull(businessMapper.selectById(id)); + } + + @Test + public void testDeleteBusiness_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> businessService.deleteBusiness(id), BUSINESS_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetBusinessPage() { + // mock 数据 + CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStatusTypeId(null); + o.setStatusId(null); + o.setContactNextTime(null); + o.setCustomerId(null); + o.setDealTime(null); + o.setPrice(null); + o.setDiscountPercent(null); + o.setProductPrice(null); + o.setRemark(null); + o.setCreateTime(null); + o.setEndStatus(null); + o.setEndRemark(null); + o.setContactLastTime(null); + o.setFollowUpStatus(null); + }); + businessMapper.insert(dbBusiness); + // 测试 name 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setName(null))); + // 测试 statusTypeId 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setStatusTypeId(null))); + // 测试 statusId 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setStatusId(null))); + // 测试 contactNextTime 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setContactNextTime(null))); + // 测试 customerId 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setCustomerId(null))); + // 测试 dealTime 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setDealTime(null))); + // 测试 price 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setPrice(null))); + // 测试 discountPercent 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setDiscountPercent(null))); + // 测试 productPrice 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setProductPrice(null))); + // 测试 remark 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setRemark(null))); + // 测试 createTime 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setCreateTime(null))); + // 测试 endStatus 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setEndStatus(null))); + // 测试 endRemark 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setEndRemark(null))); + // 测试 contactLastTime 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setContactLastTime(null))); + // 测试 followUpStatus 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setFollowUpStatus(null))); + //// 准备参数 + //CrmBusinessPageReqVO reqVO = new CrmBusinessPageReqVO(); + //reqVO.setName(null); + //reqVO.setStatusTypeId(null); + //reqVO.setStatusId(null); + //reqVO.setContactNextTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + //reqVO.setCustomerId(null); + //reqVO.setDealTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + //reqVO.setPrice(null); + //reqVO.setDiscountPercent(null); + //reqVO.setProductPrice(null); + //reqVO.setRemark(null); + //reqVO.setOwnerUserId(null); + //reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + //reqVO.setRoUserIds(null); + //reqVO.setRwUserIds(null); + //reqVO.setEndStatus(null); + //reqVO.setEndRemark(null); + //reqVO.setContactLastTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + //reqVO.setFollowUpStatus(null); + // + //// 调用 + //PageResult pageResult = businessService.getBusinessPage(reqVO); + //// 断言 + //assertEquals(1, pageResult.getTotal()); + //assertEquals(1, pageResult.getList().size()); + //assertPojoEquals(dbBusiness, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetBusinessList() { + // mock 数据 + CrmBusinessDO dbBusiness = randomPojo(CrmBusinessDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStatusTypeId(null); + o.setStatusId(null); + o.setContactNextTime(null); + o.setCustomerId(null); + o.setDealTime(null); + o.setPrice(null); + o.setDiscountPercent(null); + o.setProductPrice(null); + o.setRemark(null); + o.setCreateTime(null); + o.setEndStatus(null); + o.setEndRemark(null); + o.setContactLastTime(null); + o.setFollowUpStatus(null); + }); + businessMapper.insert(dbBusiness); + // 测试 name 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setName(null))); + // 测试 statusTypeId 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setStatusTypeId(null))); + // 测试 statusId 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setStatusId(null))); + // 测试 contactNextTime 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setContactNextTime(null))); + // 测试 customerId 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setCustomerId(null))); + // 测试 dealTime 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setDealTime(null))); + // 测试 price 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setPrice(null))); + // 测试 discountPercent 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setDiscountPercent(null))); + // 测试 productPrice 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setProductPrice(null))); + // 测试 remark 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setRemark(null))); + // 测试 createTime 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setCreateTime(null))); + // 测试 endStatus 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setEndStatus(null))); + // 测试 endRemark 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setEndRemark(null))); + // 测试 contactLastTime 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setContactLastTime(null))); + // 测试 followUpStatus 不匹配 + businessMapper.insert(cloneIgnoreId(dbBusiness, o -> o.setFollowUpStatus(null))); + // 准备参数 + CrmBusinessExportReqVO reqVO = new CrmBusinessExportReqVO(); + reqVO.setName(null); + reqVO.setStatusTypeId(null); + reqVO.setStatusId(null); + reqVO.setContactNextTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setCustomerId(null); + reqVO.setDealTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setPrice(null); + reqVO.setDiscountPercent(null); + reqVO.setProductPrice(null); + reqVO.setRemark(null); + reqVO.setOwnerUserId(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setRoUserIds(null); + reqVO.setRwUserIds(null); + reqVO.setEndStatus(null); + reqVO.setEndRemark(null); + reqVO.setContactLastTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setFollowUpStatus(null); + + // 调用 + List list = businessService.getBusinessList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbBusiness, list.get(0)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusServiceImplTest.java new file mode 100644 index 000000000..9a59f3bd2 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/businessstatus/CrmBusinessStatusServiceImplTest.java @@ -0,0 +1,168 @@ +package cn.iocoder.yudao.module.crm.service.businessstatus; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatus.vo.CrmBusinessStatusUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatus.CrmBusinessStatusDO; +import cn.iocoder.yudao.module.crm.dal.mysql.businessstatus.CrmBusinessStatusMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +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.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link CrmBusinessStatusServiceImpl} 的单元测试类 + * + * @author ljlleo + */ +@Import(CrmBusinessStatusServiceImpl.class) +public class CrmBusinessStatusServiceImplTest extends BaseDbUnitTest { + + @Resource + private CrmBusinessStatusServiceImpl businessStatusService; + + @Resource + private CrmBusinessStatusMapper businessStatusMapper; + + @Test + public void testCreateBusinessStatus_success() { + // 准备参数 + CrmBusinessStatusCreateReqVO reqVO = randomPojo(CrmBusinessStatusCreateReqVO.class); + + // 调用 + Long businessStatusId = businessStatusService.createBusinessStatus(reqVO); + // 断言 + assertNotNull(businessStatusId); + // 校验记录的属性是否正确 + CrmBusinessStatusDO businessStatus = businessStatusMapper.selectById(businessStatusId); + assertPojoEquals(reqVO, businessStatus); + } + + @Test + public void testUpdateBusinessStatus_success() { + // mock 数据 + CrmBusinessStatusDO dbBusinessStatus = randomPojo(CrmBusinessStatusDO.class); + businessStatusMapper.insert(dbBusinessStatus);// @Sql: 先插入出一条存在的数据 + // 准备参数 + CrmBusinessStatusUpdateReqVO reqVO = randomPojo(CrmBusinessStatusUpdateReqVO.class, o -> { + o.setId(dbBusinessStatus.getId()); // 设置更新的 ID + }); + + // 调用 + businessStatusService.updateBusinessStatus(reqVO); + // 校验是否更新正确 + CrmBusinessStatusDO businessStatus = businessStatusMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, businessStatus); + } + + @Test + public void testUpdateBusinessStatus_notExists() { + // 准备参数 + CrmBusinessStatusUpdateReqVO reqVO = randomPojo(CrmBusinessStatusUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> businessStatusService.updateBusinessStatus(reqVO), BUSINESS_STATUS_NOT_EXISTS); + } + + @Test + public void testDeleteBusinessStatus_success() { + // mock 数据 + CrmBusinessStatusDO dbBusinessStatus = randomPojo(CrmBusinessStatusDO.class); + businessStatusMapper.insert(dbBusinessStatus);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbBusinessStatus.getId(); + + // 调用 + businessStatusService.deleteBusinessStatus(id); + // 校验数据不存在了 + assertNull(businessStatusMapper.selectById(id)); + } + + @Test + public void testDeleteBusinessStatus_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> businessStatusService.deleteBusinessStatus(id), BUSINESS_STATUS_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetBusinessStatusPage() { + // mock 数据 + CrmBusinessStatusDO dbBusinessStatus = randomPojo(CrmBusinessStatusDO.class, o -> { // 等会查询到 + o.setTypeId(null); + o.setName(null); + o.setPercent(null); + o.setSort(null); + }); + businessStatusMapper.insert(dbBusinessStatus); + // 测试 typeId 不匹配 + businessStatusMapper.insert(cloneIgnoreId(dbBusinessStatus, o -> o.setTypeId(null))); + // 测试 name 不匹配 + businessStatusMapper.insert(cloneIgnoreId(dbBusinessStatus, o -> o.setName(null))); + // 测试 percent 不匹配 + businessStatusMapper.insert(cloneIgnoreId(dbBusinessStatus, o -> o.setPercent(null))); + // 测试 sort 不匹配 + businessStatusMapper.insert(cloneIgnoreId(dbBusinessStatus, o -> o.setSort(null))); + // 准备参数 + //CrmBusinessStatusPageReqVO reqVO = new CrmBusinessStatusPageReqVO(); + //reqVO.setTypeId(null); + //reqVO.setName(null); + //reqVO.setPercent(null); + //reqVO.setSort(null); + // + //// 调用 + //PageResult pageResult = businessStatusService.getBusinessStatusPage(reqVO); + //// 断言 + //assertEquals(1, pageResult.getTotal()); + //assertEquals(1, pageResult.getList().size()); + //assertPojoEquals(dbBusinessStatus, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetBusinessStatusList() { + // mock 数据 + CrmBusinessStatusDO dbBusinessStatus = randomPojo(CrmBusinessStatusDO.class, o -> { // 等会查询到 + o.setTypeId(null); + o.setName(null); + o.setPercent(null); + o.setSort(null); + }); + businessStatusMapper.insert(dbBusinessStatus); + // 测试 typeId 不匹配 + businessStatusMapper.insert(cloneIgnoreId(dbBusinessStatus, o -> o.setTypeId(null))); + // 测试 name 不匹配 + businessStatusMapper.insert(cloneIgnoreId(dbBusinessStatus, o -> o.setName(null))); + // 测试 percent 不匹配 + businessStatusMapper.insert(cloneIgnoreId(dbBusinessStatus, o -> o.setPercent(null))); + // 测试 sort 不匹配 + businessStatusMapper.insert(cloneIgnoreId(dbBusinessStatus, o -> o.setSort(null))); + // 准备参数 + CrmBusinessStatusExportReqVO reqVO = new CrmBusinessStatusExportReqVO(); + reqVO.setTypeId(null); + reqVO.setName(null); + reqVO.setPercent(null); + reqVO.setSort(null); + + // 调用 + List list = businessStatusService.getBusinessStatusList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbBusinessStatus, list.get(0)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeServiceImplTest.java new file mode 100644 index 000000000..bf778b989 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/businessstatustype/CrmBusinessStatusTypeServiceImplTest.java @@ -0,0 +1,171 @@ +package cn.iocoder.yudao.module.crm.service.businessstatustype; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.businessstatustype.vo.CrmBusinessStatusTypeUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.businessstatustype.CrmBusinessStatusTypeDO; +import cn.iocoder.yudao.module.crm.dal.mysql.businessstatustype.CrmBusinessStatusTypeMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +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.crm.enums.ErrorCodeConstants.BUSINESS_STATUS_TYPE_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link CrmBusinessStatusTypeServiceImpl} 的单元测试类 + * + * @author ljlleo + */ +@Import(CrmBusinessStatusTypeServiceImpl.class) +public class CrmBusinessStatusTypeServiceImplTest extends BaseDbUnitTest { + + @Resource + private CrmBusinessStatusTypeServiceImpl businessStatusTypeService; + + @Resource + private CrmBusinessStatusTypeMapper businessStatusTypeMapper; + + @Test + public void testCreateBusinessStatusType_success() { + // 准备参数 + CrmBusinessStatusTypeCreateReqVO reqVO = randomPojo(CrmBusinessStatusTypeCreateReqVO.class); + + // 调用 + Long businessStatusTypeId = businessStatusTypeService.createBusinessStatusType(reqVO); + // 断言 + assertNotNull(businessStatusTypeId); + // 校验记录的属性是否正确 + CrmBusinessStatusTypeDO businessStatusType = businessStatusTypeMapper.selectById(businessStatusTypeId); + assertPojoEquals(reqVO, businessStatusType); + } + + @Test + public void testUpdateBusinessStatusType_success() { + // mock 数据 + CrmBusinessStatusTypeDO dbBusinessStatusType = randomPojo(CrmBusinessStatusTypeDO.class); + businessStatusTypeMapper.insert(dbBusinessStatusType);// @Sql: 先插入出一条存在的数据 + // 准备参数 + CrmBusinessStatusTypeUpdateReqVO reqVO = randomPojo(CrmBusinessStatusTypeUpdateReqVO.class, o -> { + o.setId(dbBusinessStatusType.getId()); // 设置更新的 ID + }); + + // 调用 + businessStatusTypeService.updateBusinessStatusType(reqVO); + // 校验是否更新正确 + CrmBusinessStatusTypeDO businessStatusType = businessStatusTypeMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, businessStatusType); + } + + @Test + public void testUpdateBusinessStatusType_notExists() { + // 准备参数 + CrmBusinessStatusTypeUpdateReqVO reqVO = randomPojo(CrmBusinessStatusTypeUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> businessStatusTypeService.updateBusinessStatusType(reqVO), BUSINESS_STATUS_TYPE_NOT_EXISTS); + } + + @Test + public void testDeleteBusinessStatusType_success() { + // mock 数据 + CrmBusinessStatusTypeDO dbBusinessStatusType = randomPojo(CrmBusinessStatusTypeDO.class); + businessStatusTypeMapper.insert(dbBusinessStatusType);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbBusinessStatusType.getId(); + + // 调用 + businessStatusTypeService.deleteBusinessStatusType(id); + // 校验数据不存在了 + assertNull(businessStatusTypeMapper.selectById(id)); + } + + @Test + public void testDeleteBusinessStatusType_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> businessStatusTypeService.deleteBusinessStatusType(id), BUSINESS_STATUS_TYPE_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetBusinessStatusTypePage() { + // mock 数据 + CrmBusinessStatusTypeDO dbBusinessStatusType = randomPojo(CrmBusinessStatusTypeDO.class, o -> { // 等会查询到 + o.setName(null); + o.setDeptIds(null); + o.setStatus(null); + //o.setCreateTime(null); + }); + businessStatusTypeMapper.insert(dbBusinessStatusType); + // 测试 name 不匹配 + businessStatusTypeMapper.insert(cloneIgnoreId(dbBusinessStatusType, o -> o.setName(null))); + // 测试 deptIds 不匹配 + businessStatusTypeMapper.insert(cloneIgnoreId(dbBusinessStatusType, o -> o.setDeptIds(null))); + // 测试 status 不匹配 + businessStatusTypeMapper.insert(cloneIgnoreId(dbBusinessStatusType, o -> o.setStatus(null))); + // 测试 createTime 不匹配 + //businessStatusTypeMapper.insert(cloneIgnoreId(dbBusinessStatusType, o -> o.setCreateTime(null))); + // 准备参数 + CrmBusinessStatusTypePageReqVO reqVO = new CrmBusinessStatusTypePageReqVO(); + reqVO.setName(null); + //reqVO.setDeptIds(null); + reqVO.setStatus(null); + //reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = businessStatusTypeService.getBusinessStatusTypePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbBusinessStatusType, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetBusinessStatusTypeList() { + // mock 数据 + CrmBusinessStatusTypeDO dbBusinessStatusType = randomPojo(CrmBusinessStatusTypeDO.class, o -> { // 等会查询到 + o.setName(null); + o.setDeptIds(null); + o.setStatus(null); + //o.setCreateTime(null); + }); + businessStatusTypeMapper.insert(dbBusinessStatusType); + // 测试 name 不匹配 + businessStatusTypeMapper.insert(cloneIgnoreId(dbBusinessStatusType, o -> o.setName(null))); + // 测试 deptIds 不匹配 + businessStatusTypeMapper.insert(cloneIgnoreId(dbBusinessStatusType, o -> o.setDeptIds(null))); + // 测试 status 不匹配 + businessStatusTypeMapper.insert(cloneIgnoreId(dbBusinessStatusType, o -> o.setStatus(null))); + // 测试 createTime 不匹配 + //businessStatusTypeMapper.insert(cloneIgnoreId(dbBusinessStatusType, o -> o.setCreateTime(null))); + // 准备参数 + CrmBusinessStatusTypeExportReqVO reqVO = new CrmBusinessStatusTypeExportReqVO(); + reqVO.setName(null); + reqVO.setDeptIds(null); + reqVO.setStatus(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + List list = businessStatusTypeService.getBusinessStatusTypeList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbBusinessStatusType, list.get(0)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java new file mode 100644 index 000000000..4757e921d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java @@ -0,0 +1,214 @@ +package cn.iocoder.yudao.module.crm.service.clue; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +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.crm.enums.ErrorCodeConstants.CLUE_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +// TODO 芋艿:单测后续补; +/** + * {@link CrmClueServiceImpl} 的单元测试类 + * + * @author Wanwan + */ +@Import(CrmClueServiceImpl.class) +public class CrmClueServiceImplTest extends BaseDbUnitTest { + + @Resource + private CrmClueServiceImpl clueService; + + @Resource + private CrmClueMapper clueMapper; + + @Test + public void testCreateClue_success() { + // 准备参数 + CrmClueCreateReqVO reqVO = randomPojo(CrmClueCreateReqVO.class); + + // 调用 + Long clueId = clueService.createClue(reqVO); + // 断言 + assertNotNull(clueId); + // 校验记录的属性是否正确 + CrmClueDO clue = clueMapper.selectById(clueId); + assertPojoEquals(reqVO, clue); + } + + @Test + public void testUpdateClue_success() { + // mock 数据 + CrmClueDO dbClue = randomPojo(CrmClueDO.class); + clueMapper.insert(dbClue);// @Sql: 先插入出一条存在的数据 + // 准备参数 + CrmClueUpdateReqVO reqVO = randomPojo(CrmClueUpdateReqVO.class, o -> { + o.setId(dbClue.getId()); // 设置更新的 ID + }); + + // 调用 + clueService.updateClue(reqVO); + // 校验是否更新正确 + CrmClueDO clue = clueMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, clue); + } + + @Test + public void testUpdateClue_notExists() { + // 准备参数 + CrmClueUpdateReqVO reqVO = randomPojo(CrmClueUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> clueService.updateClue(reqVO), CLUE_NOT_EXISTS); + } + + @Test + public void testDeleteClue_success() { + // mock 数据 + CrmClueDO dbClue = randomPojo(CrmClueDO.class); + clueMapper.insert(dbClue);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbClue.getId(); + + // 调用 + clueService.deleteClue(id); + // 校验数据不存在了 + assertNull(clueMapper.selectById(id)); + } + + @Test + public void testDeleteClue_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> clueService.deleteClue(id), CLUE_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCluePage() { + // mock 数据 + CrmClueDO dbClue = randomPojo(CrmClueDO.class, o -> { // 等会查询到 + o.setTransformStatus(null); + o.setFollowUpStatus(null); + o.setName(null); + o.setCustomerId(null); + o.setContactNextTime(null); + o.setTelephone(null); + o.setMobile(null); + o.setAddress(null); + o.setContactLastTime(null); + o.setCreateTime(null); + }); + clueMapper.insert(dbClue); + // 测试 transformStatus 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTransformStatus(null))); + // 测试 followUpStatus 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setFollowUpStatus(null))); + // 测试 name 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setName(null))); + // 测试 customerId 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCustomerId(null))); + // 测试 contactNextTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactNextTime(null))); + // 测试 telephone 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTelephone(null))); + // 测试 mobile 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setMobile(null))); + // 测试 address 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setAddress(null))); + // 测试 contactLastTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactLastTime(null))); + // 测试 createTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCreateTime(null))); + // 准备参数 + CrmCluePageReqVO reqVO = new CrmCluePageReqVO(); + reqVO.setName(null); + reqVO.setTelephone(null); + reqVO.setMobile(null); + + // 调用 + PageResult pageResult = clueService.getCluePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbClue, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetClueList() { + // mock 数据 + CrmClueDO dbClue = randomPojo(CrmClueDO.class, o -> { // 等会查询到 + o.setTransformStatus(null); + o.setFollowUpStatus(null); + o.setName(null); + o.setCustomerId(null); + o.setContactNextTime(null); + o.setTelephone(null); + o.setMobile(null); + o.setAddress(null); + o.setContactLastTime(null); + o.setCreateTime(null); + }); + clueMapper.insert(dbClue); + // 测试 transformStatus 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTransformStatus(null))); + // 测试 followUpStatus 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setFollowUpStatus(null))); + // 测试 name 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setName(null))); + // 测试 customerId 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCustomerId(null))); + // 测试 contactNextTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactNextTime(null))); + // 测试 telephone 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTelephone(null))); + // 测试 mobile 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setMobile(null))); + // 测试 address 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setAddress(null))); + // 测试 contactLastTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactLastTime(null))); + // 测试 createTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCreateTime(null))); + // 准备参数 + CrmClueExportReqVO reqVO = new CrmClueExportReqVO(); + reqVO.setTransformStatus(null); + reqVO.setFollowUpStatus(null); + reqVO.setName(null); + reqVO.setCustomerId(null); + reqVO.setContactNextTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setTelephone(null); + reqVO.setMobile(null); + reqVO.setAddress(null); + reqVO.setOwnerUserId(null); + reqVO.setContactLastTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + List list = clueService.getClueList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbClue, list.get(0)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java new file mode 100644 index 000000000..1406b5916 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java @@ -0,0 +1,196 @@ +package cn.iocoder.yudao.module.crm.service.contract; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.ContractUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.ContractDO; +import cn.iocoder.yudao.module.crm.dal.mysql.contract.ContractMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +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.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link ContractServiceImpl} 的单元测试类 + * + * @author dhb52 + */ +@Import(ContractServiceImpl.class) +public class ContractServiceImplTest extends BaseDbUnitTest { + + @Resource + private ContractServiceImpl contractService; + + @Resource + private ContractMapper contractMapper; + + @Test + public void testCreateContract_success() { + // 准备参数 + ContractCreateReqVO reqVO = randomPojo(ContractCreateReqVO.class); + + // 调用 + Long contractId = contractService.createContract(reqVO, getLoginUserId()); + // 断言 + assertNotNull(contractId); + // 校验记录的属性是否正确 + ContractDO contract = contractMapper.selectById(contractId); + assertPojoEquals(reqVO, contract); + } + + @Test + public void testUpdateContract_success() { + // mock 数据 + ContractDO dbContract = randomPojo(ContractDO.class); + contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ContractUpdateReqVO reqVO = randomPojo(ContractUpdateReqVO.class, o -> { + o.setId(dbContract.getId()); // 设置更新的 ID + }); + + // 调用 + contractService.updateContract(reqVO); + // 校验是否更新正确 + ContractDO contract = contractMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, contract); + } + + @Test + public void testUpdateContract_notExists() { + // 准备参数 + ContractUpdateReqVO reqVO = randomPojo(ContractUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> contractService.updateContract(reqVO), CONTRACT_NOT_EXISTS); + } + + @Test + public void testDeleteContract_success() { + // mock 数据 + ContractDO dbContract = randomPojo(ContractDO.class); + contractMapper.insert(dbContract);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbContract.getId(); + + // 调用 + contractService.deleteContract(id); + // 校验数据不存在了 + assertNull(contractMapper.selectById(id)); + } + + @Test + public void testDeleteContract_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> contractService.deleteContract(id), CONTRACT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetContractPage() { + // mock 数据 + ContractDO dbContract = randomPojo(ContractDO.class, o -> { // 等会查询到 + o.setName(null); + o.setCustomerId(null); + o.setBusinessId(null); + o.setOrderDate(null); + o.setNo(null); + o.setDiscountPercent(null); + o.setProductPrice(null); + }); + contractMapper.insert(dbContract); + // 测试 name 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setName(null))); + // 测试 customerId 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setCustomerId(null))); + // 测试 businessId 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setBusinessId(null))); + // 测试 orderDate 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setOrderDate(null))); + // 测试 no 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setNo(null))); + // 测试 discountPercent 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setDiscountPercent(null))); + // 测试 productPrice 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setProductPrice(null))); + // 准备参数 + ContractPageReqVO reqVO = new ContractPageReqVO(); + reqVO.setName(null); + reqVO.setCustomerId(null); + reqVO.setBusinessId(null); + reqVO.setOrderDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setNo(null); + reqVO.setDiscountPercent(null); + reqVO.setProductPrice(null); + + // 调用 + PageResult pageResult = contractService.getContractPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbContract, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetContractList() { + // mock 数据 + ContractDO dbContract = randomPojo(ContractDO.class, o -> { // 等会查询到 + o.setName("合同名称"); + o.setCustomerId(null); + o.setBusinessId(null); + o.setOrderDate(null); + o.setNo(null); + o.setDiscountPercent(null); + o.setProductPrice(null); + }); + contractMapper.insert(dbContract); + // 测试 name 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setName(null))); + // 测试 customerId 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setCustomerId(null))); + // 测试 businessId 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setBusinessId(null))); + // 测试 orderDate 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setOrderDate(null))); + // 测试 no 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setNo(null))); + // 测试 discountPercent 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setDiscountPercent(null))); + // 测试 productPrice 不匹配 + contractMapper.insert(cloneIgnoreId(dbContract, o -> o.setProductPrice(null))); + // 准备参数 + ContractExportReqVO reqVO = new ContractExportReqVO(); + reqVO.setName(null); + reqVO.setCustomerId(null); + reqVO.setBusinessId(null); + reqVO.setOrderDate(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setNo(null); + reqVO.setDiscountPercent(null); + reqVO.setProductPrice(null); + + // 调用 + List list = contractService.getContractList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbContract, list.get(0)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java new file mode 100644 index 000000000..41dd14f92 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java @@ -0,0 +1,173 @@ +package cn.iocoder.yudao.module.crm.service.customer; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +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.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +// TODO 芋艿:单测后续补 + +/** + * {@link CrmCustomerServiceImpl} 的单元测试类 + * + * @author Wanwan + */ +@Import(CrmCustomerServiceImpl.class) +public class CrmCustomerServiceImplTest extends BaseDbUnitTest { + + @Resource + private CrmCustomerServiceImpl customerService; + + @Resource + private CrmCustomerMapper customerMapper; + + @Test + public void testCreateCustomer_success() { + // 准备参数 + CrmCustomerCreateReqVO reqVO = randomPojo(CrmCustomerCreateReqVO.class); + + // 调用 + Long customerId = customerService.createCustomer(reqVO, getLoginUserId()); + // 断言 + assertNotNull(customerId); + // 校验记录的属性是否正确 + CrmCustomerDO customer = customerMapper.selectById(customerId); + assertPojoEquals(reqVO, customer); + } + + @Test + public void testUpdateCustomer_success() { + // mock 数据 + CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class); + customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 + // 准备参数 + CrmCustomerUpdateReqVO reqVO = randomPojo(CrmCustomerUpdateReqVO.class, o -> { + o.setId(dbCustomer.getId()); // 设置更新的 ID + }); + + // 调用 + customerService.updateCustomer(reqVO); + // 校验是否更新正确 + CrmCustomerDO customer = customerMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, customer); + } + + @Test + public void testUpdateCustomer_notExists() { + // 准备参数 + CrmCustomerUpdateReqVO reqVO = randomPojo(CrmCustomerUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> customerService.updateCustomer(reqVO), CUSTOMER_NOT_EXISTS); + } + + @Test + public void testDeleteCustomer_success() { + // mock 数据 + CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class); + customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCustomer.getId(); + + // 调用 + customerService.deleteCustomer(id); + // 校验数据不存在了 + assertNull(customerMapper.selectById(id)); + } + + @Test + public void testDeleteCustomer_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> customerService.deleteCustomer(id), CUSTOMER_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCustomerPage() { + // mock 数据 + CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class, o -> { // 等会查询到 + o.setName(null); + o.setMobile(null); + o.setTelephone(null); + o.setWebsite(null); + }); + customerMapper.insert(dbCustomer); + // 测试 name 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null))); + // 测试 mobile 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null))); + // 测试 telephone 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null))); + // 测试 website 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setWebsite(null))); + // 准备参数 + CrmCustomerPageReqVO reqVO = new CrmCustomerPageReqVO(); + reqVO.setName(null); + reqVO.setMobile(null); + //reqVO.setTelephone(null); + //reqVO.setWebsite(null); + + // 调用 + PageResult pageResult = customerService.getCustomerPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbCustomer, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCustomerList() { + // mock 数据 + CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class, o -> { // 等会查询到 + o.setName(null); + o.setMobile(null); + o.setTelephone(null); + o.setWebsite(null); + }); + customerMapper.insert(dbCustomer); + // 测试 name 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null))); + // 测试 mobile 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null))); + // 测试 telephone 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null))); + // 测试 website 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setWebsite(null))); + // 准备参数 + CrmCustomerExportReqVO reqVO = new CrmCustomerExportReqVO(); + reqVO.setName(null); + reqVO.setMobile(null); + //reqVO.setTelephone(null); + //reqVO.setWebsite(null); + + // 调用 + List list = customerService.getCustomerList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbCustomer, list.get(0)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanServiceImplTest.java new file mode 100644 index 000000000..3739481c0 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivablePlanServiceImplTest.java @@ -0,0 +1,228 @@ +package cn.iocoder.yudao.module.crm.service.receivable; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePlanCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePlanExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePlanPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePlanUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivablePlanDO; +import cn.iocoder.yudao.module.crm.dal.mysql.receivable.ReceivablePlanMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +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.crm.enums.ErrorCodeConstants.RECEIVABLE_PLAN_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +// TODO 芋艿:后续,需要补充测试用例 +/** + * {@link ReceivablePlanServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ReceivablePlanServiceImpl.class) +public class ReceivablePlanServiceImplTest extends BaseDbUnitTest { + + @Resource + private ReceivablePlanServiceImpl receivablePlanService; + + @Resource + private ReceivablePlanMapper receivablePlanMapper; + + @Test + public void testCreateReceivablePlan_success() { + // 准备参数 + ReceivablePlanCreateReqVO reqVO = randomPojo(ReceivablePlanCreateReqVO.class); + + // 调用 + Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO); + // 断言 + assertNotNull(receivablePlanId); + // 校验记录的属性是否正确 + ReceivablePlanDO receivablePlan = receivablePlanMapper.selectById(receivablePlanId); + assertPojoEquals(reqVO, receivablePlan); + } + + @Test + public void testUpdateReceivablePlan_success() { + // mock 数据 + ReceivablePlanDO dbReceivablePlan = randomPojo(ReceivablePlanDO.class); + receivablePlanMapper.insert(dbReceivablePlan);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ReceivablePlanUpdateReqVO reqVO = randomPojo(ReceivablePlanUpdateReqVO.class, o -> { + o.setId(dbReceivablePlan.getId()); // 设置更新的 ID + }); + + // 调用 + receivablePlanService.updateReceivablePlan(reqVO); + // 校验是否更新正确 + ReceivablePlanDO receivablePlan = receivablePlanMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, receivablePlan); + } + + @Test + public void testUpdateReceivablePlan_notExists() { + // 准备参数 + ReceivablePlanUpdateReqVO reqVO = randomPojo(ReceivablePlanUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> receivablePlanService.updateReceivablePlan(reqVO), RECEIVABLE_PLAN_NOT_EXISTS); + } + + @Test + public void testDeleteReceivablePlan_success() { + // mock 数据 + ReceivablePlanDO dbReceivablePlan = randomPojo(ReceivablePlanDO.class); + receivablePlanMapper.insert(dbReceivablePlan);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbReceivablePlan.getId(); + + // 调用 + receivablePlanService.deleteReceivablePlan(id); + // 校验数据不存在了 + assertNull(receivablePlanMapper.selectById(id)); + } + + @Test + public void testDeleteReceivablePlan_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> receivablePlanService.deleteReceivablePlan(id), RECEIVABLE_PLAN_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetReceivablePlanPage() { + // mock 数据 + ReceivablePlanDO dbReceivablePlan = randomPojo(ReceivablePlanDO.class, o -> { // 等会查询到 + o.setIndexNo(null); + o.setStatus(null); + o.setCheckStatus(null); + o.setReturnTime(null); + o.setRemindDays(null); + o.setRemindTime(null); + o.setCustomerId(null); + o.setContractId(null); + o.setOwnerUserId(null); + o.setRemark(null); + o.setCreateTime(null); + }); + receivablePlanMapper.insert(dbReceivablePlan); + // 测试 indexNo 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setIndexNo(null))); + // 测试 status 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setStatus(null))); + // 测试 checkStatus 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCheckStatus(null))); + // 测试 returnTime 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setReturnTime(null))); + // 测试 remindDays 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setRemindDays(null))); + // 测试 remindTime 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setRemindTime(null))); + // 测试 customerId 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null))); + // 测试 contractId 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null))); + // 测试 ownerUserId 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setOwnerUserId(null))); + // 测试 remark 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setRemark(null))); + // 测试 createTime 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCreateTime(null))); + // 准备参数 + ReceivablePlanPageReqVO reqVO = new ReceivablePlanPageReqVO(); + reqVO.setIndexNo(null); + reqVO.setStatus(null); + reqVO.setCheckStatus(null); + reqVO.setReturnTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setRemindDays(null); + reqVO.setRemindTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setCustomerId(null); + reqVO.setContractId(null); + reqVO.setOwnerUserId(null); + reqVO.setRemark(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = receivablePlanService.getReceivablePlanPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetReceivablePlanList() { + // mock 数据 + ReceivablePlanDO dbReceivablePlan = randomPojo(ReceivablePlanDO.class, o -> { // 等会查询到 + o.setIndexNo(null); + o.setStatus(null); + o.setCheckStatus(null); + o.setReturnTime(null); + o.setRemindDays(null); + o.setRemindTime(null); + o.setCustomerId(null); + o.setContractId(null); + o.setOwnerUserId(null); + o.setRemark(null); + o.setCreateTime(null); + }); + receivablePlanMapper.insert(dbReceivablePlan); + // 测试 indexNo 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setIndexNo(null))); + // 测试 status 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setStatus(null))); + // 测试 checkStatus 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCheckStatus(null))); + // 测试 returnTime 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setReturnTime(null))); + // 测试 remindDays 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setRemindDays(null))); + // 测试 remindTime 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setRemindTime(null))); + // 测试 customerId 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null))); + // 测试 contractId 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null))); + // 测试 ownerUserId 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setOwnerUserId(null))); + // 测试 remark 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setRemark(null))); + // 测试 createTime 不匹配 + receivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCreateTime(null))); + // 准备参数 + ReceivablePlanExportReqVO reqVO = new ReceivablePlanExportReqVO(); + reqVO.setIndexNo(null); + reqVO.setStatus(null); + reqVO.setCheckStatus(null); + reqVO.setReturnTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setRemindDays(null); + reqVO.setRemindTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setCustomerId(null); + reqVO.setContractId(null); + reqVO.setOwnerUserId(null); + reqVO.setRemark(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + List list = receivablePlanService.getReceivablePlanList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbReceivablePlan, list.get(0)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableServiceImplTest.java new file mode 100644 index 000000000..b8d4018b4 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/ReceivableServiceImplTest.java @@ -0,0 +1,276 @@ +package cn.iocoder.yudao.module.crm.service.receivable; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivableCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivableExportReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivablePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.ReceivableUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.ReceivableDO; +import cn.iocoder.yudao.module.crm.dal.mysql.receivable.ReceivableMapper; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +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.crm.enums.ErrorCodeConstants.RECEIVABLE_NOT_EXISTS; +import static org.junit.jupiter.api.Assertions.*; + +// TODO 芋艿:等实现完,在校验下; +/** + * {@link ReceivableServiceImpl} 的单元测试类 + * + * @author 赤焰 + */ +@Import(ReceivableServiceImpl.class) +public class ReceivableServiceImplTest extends BaseDbUnitTest { + + @Resource + private ReceivableServiceImpl receivableService; + + @Resource + private ReceivableMapper receivableMapper; + + @Test + public void testCreateReceivable_success() { + // 准备参数 + ReceivableCreateReqVO reqVO = randomPojo(ReceivableCreateReqVO.class); + + // 调用 + Long receivableId = receivableService.createReceivable(reqVO); + // 断言 + assertNotNull(receivableId); + // 校验记录的属性是否正确 + ReceivableDO receivable = receivableMapper.selectById(receivableId); + assertPojoEquals(reqVO, receivable); + } + + @Test + public void testUpdateReceivable_success() { + // mock 数据 + ReceivableDO dbReceivable = randomPojo(ReceivableDO.class); + receivableMapper.insert(dbReceivable);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ReceivableUpdateReqVO reqVO = randomPojo(ReceivableUpdateReqVO.class, o -> { + o.setId(dbReceivable.getId()); // 设置更新的 ID + }); + + // 调用 + receivableService.updateReceivable(reqVO); + // 校验是否更新正确 + ReceivableDO receivable = receivableMapper.selectById(reqVO.getId()); // 获取最新的 + assertPojoEquals(reqVO, receivable); + } + + @Test + public void testUpdateReceivable_notExists() { + // 准备参数 + ReceivableUpdateReqVO reqVO = randomPojo(ReceivableUpdateReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> receivableService.updateReceivable(reqVO), RECEIVABLE_NOT_EXISTS); + } + + @Test + public void testDeleteReceivable_success() { + // mock 数据 + ReceivableDO dbReceivable = randomPojo(ReceivableDO.class); + receivableMapper.insert(dbReceivable);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbReceivable.getId(); + + // 调用 + receivableService.deleteReceivable(id); + // 校验数据不存在了 + assertNull(receivableMapper.selectById(id)); + } + + @Test + public void testDeleteReceivable_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> receivableService.deleteReceivable(id), RECEIVABLE_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetReceivablePage() { + // mock 数据 + ReceivableDO dbReceivable = randomPojo(ReceivableDO.class, o -> { // 等会查询到 + o.setNo(null); + o.setPlanId(null); + o.setCustomerId(null); + o.setContractId(null); + o.setCheckStatus(null); + o.setProcessInstanceId(null); + o.setReturnTime(null); + o.setReturnType(null); + o.setPrice(null); + o.setOwnerUserId(null); + o.setBatchId(null); + o.setSort(null); + o.setDataScope(null); + o.setDataScopeDeptIds(null); + o.setStatus(null); + o.setRemark(null); + o.setCreateTime(null); + }); + receivableMapper.insert(dbReceivable); + // 测试 no 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setNo(null))); + // 测试 planId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setPlanId(null))); + // 测试 customerId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setCustomerId(null))); + // 测试 contractId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setContractId(null))); + // 测试 checkStatus 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setCheckStatus(null))); + // 测试 processInstanceId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setProcessInstanceId(null))); + // 测试 returnTime 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setReturnTime(null))); + // 测试 returnType 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setReturnType(null))); + // 测试 price 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setPrice(null))); + // 测试 ownerUserId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setOwnerUserId(null))); + // 测试 batchId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setBatchId(null))); + // 测试 sort 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setSort(null))); + // 测试 dataScope 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setDataScope(null))); + // 测试 dataScopeDeptIds 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setDataScopeDeptIds(null))); + // 测试 status 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setStatus(null))); + // 测试 remark 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setRemark(null))); + // 测试 createTime 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setCreateTime(null))); + // 准备参数 + ReceivablePageReqVO reqVO = new ReceivablePageReqVO(); + reqVO.setNo(null); + reqVO.setPlanId(null); + reqVO.setCustomerId(null); + reqVO.setContractId(null); + reqVO.setCheckStatus(null); + reqVO.setProcessInstanceId(null); + reqVO.setReturnTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setReturnType(null); + reqVO.setPrice(null); + reqVO.setOwnerUserId(null); + reqVO.setBatchId(null); + reqVO.setSort(null); + reqVO.setDataScope(null); + reqVO.setDataScopeDeptIds(null); + reqVO.setStatus(null); + reqVO.setRemark(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = receivableService.getReceivablePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbReceivable, pageResult.getList().get(0)); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetReceivableList() { + // mock 数据 + ReceivableDO dbReceivable = randomPojo(ReceivableDO.class, o -> { // 等会查询到 + o.setNo(null); + o.setPlanId(null); + o.setCustomerId(null); + o.setContractId(null); + o.setCheckStatus(null); + o.setProcessInstanceId(null); + o.setReturnTime(null); + o.setReturnType(null); + o.setPrice(null); + o.setOwnerUserId(null); + o.setBatchId(null); + o.setSort(null); + o.setDataScope(null); + o.setDataScopeDeptIds(null); + o.setStatus(null); + o.setRemark(null); + o.setCreateTime(null); + }); + receivableMapper.insert(dbReceivable); + // 测试 no 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setNo(null))); + // 测试 planId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setPlanId(null))); + // 测试 customerId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setCustomerId(null))); + // 测试 contractId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setContractId(null))); + // 测试 checkStatus 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setCheckStatus(null))); + // 测试 processInstanceId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setProcessInstanceId(null))); + // 测试 returnTime 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setReturnTime(null))); + // 测试 returnType 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setReturnType(null))); + // 测试 price 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setPrice(null))); + // 测试 ownerUserId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setOwnerUserId(null))); + // 测试 batchId 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setBatchId(null))); + // 测试 sort 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setSort(null))); + // 测试 dataScope 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setDataScope(null))); + // 测试 dataScopeDeptIds 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setDataScopeDeptIds(null))); + // 测试 status 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setStatus(null))); + // 测试 remark 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setRemark(null))); + // 测试 createTime 不匹配 + receivableMapper.insert(cloneIgnoreId(dbReceivable, o -> o.setCreateTime(null))); + // 准备参数 + ReceivableExportReqVO reqVO = new ReceivableExportReqVO(); + reqVO.setNo(null); + reqVO.setPlanId(null); + reqVO.setCustomerId(null); + reqVO.setContractId(null); + reqVO.setCheckStatus(null); + reqVO.setProcessInstanceId(null); + reqVO.setReturnTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + reqVO.setReturnType(null); + reqVO.setPrice(null); + reqVO.setOwnerUserId(null); + reqVO.setBatchId(null); + reqVO.setSort(null); + reqVO.setDataScope(null); + reqVO.setDataScopeDeptIds(null); + reqVO.setStatus(null); + reqVO.setRemark(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + List list = receivableService.getReceivableList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbReceivable, list.get(0)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/application-unit-test.yaml b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/application-unit-test.yaml new file mode 100644 index 000000000..767f2526f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/application-unit-test.yaml @@ -0,0 +1,50 @@ +spring: + main: + lazy-initialization: true # 开启懒加载,加快速度 + banner-mode: off # 单元测试,禁用 Banner + +--- #################### 数据库相关配置 #################### + +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 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 16379 # 端口(单元测试,使用 16379 端口) + database: 0 # 数据库索引 + +mybatis-plus: + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试 + type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项(单元测试,禁用 Lock4j) + +# Resilience4j 配置项 + +--- #################### 监控相关配置 #################### + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + info: + base-package: cn.iocoder.yudao diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/logback.xml b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/logback.xml new file mode 100644 index 000000000..1d071e479 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/logback.xml @@ -0,0 +1,4 @@ + + + + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql new file mode 100644 index 000000000..c86e5a113 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/clean.sql @@ -0,0 +1,9 @@ +DELETE FROM "crm_contract"; + +DELETE FROM "crm_clue"; + +DELETE FROM "crm_receivable"; + +DELETE FROM "crm_receivable_plan"; + +DELETE FROM "crm_customer"; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql new file mode 100644 index 000000000..124edb883 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/resources/sql/create_tables.sql @@ -0,0 +1,125 @@ +CREATE TABLE IF NOT EXISTS "crm_contract" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar NOT NULL, + "customer_id" bigint, + "business_id" bigint, + "process_instance_id" bigint, + "order_date" varchar, + "owner_user_id" bigint, + "no" varchar, + "start_time" varchar, + "end_time" varchar, + "price" int, + "discount_percent" int, + "product_price" int, + "ro_user_ids" varchar, + "rw_user_ids" varchar, + "contact_id" bigint, + "sign_user_id" bigint, + "contact_last_time" varchar, + "remark" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '合同表'; + +CREATE TABLE IF NOT EXISTS "crm_clue" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "transform_status" bit NOT NULL, + "follow_up_status" bit NOT NULL, + "name" varchar NOT NULL, + "customer_id" bigint NOT NULL, + "contact_next_time" varchar, + "telephone" varchar, + "mobile" varchar, + "address" varchar, + "owner_user_id" bigint, + "contact_last_time" varchar, + "remark" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL, + PRIMARY KEY ("id") +) COMMENT '线索表'; + +CREATE TABLE IF NOT EXISTS "crm_receivable" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "no" varchar, + "plan_id" bigint, + "customer_id" bigint, + "contract_id" bigint, + "check_status" int, + "process_instance_id" bigint, + "return_time" varchar, + "return_type" varchar, + "price" varchar, + "owner_user_id" bigint, + "batch_id" bigint, + "sort" int, + "data_scope" int, + "data_scope_dept_ids" varchar, + "status" int NOT NULL, + "remark" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '回款管理'; + +CREATE TABLE IF NOT EXISTS "crm_receivable_plan" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "index_no" bigint, + "receivable_id" bigint, + "status" int NOT NULL, + "check_status" varchar, + "process_instance_id" bigint, + "price" varchar, + "return_time" varchar, + "remind_days" bigint, + "remind_time" varchar, + "customer_id" bigint, + "contract_id" bigint, + "owner_user_id" bigint, + "sort" int, + "remark" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '回款计划'; + +CREATE TABLE IF NOT EXISTS "crm_customer" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "name" varchar, + "follow_up_status" bit NOT NULL, + "lock_status" bit NOT NULL, + "deal_status" bit NOT NULL, + "mobile" varchar, + "telephone" varchar, + "website" varchar, + "remark" varchar, + "owner_user_id" bigint, + "ro_user_ids" varchar, + "rw_user_ids" varchar, + "area_id" bigint, + "detail_address" varchar, + "contact_last_time" varchar, + "contact_next_time" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL, + PRIMARY KEY ("id") +) COMMENT '客户表'; \ No newline at end of file diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 87a961778..f58aa5bd0 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -91,6 +91,13 @@ + + + cn.iocoder.boot + yudao-module-crm-biz + ${revision} + + org.springframework.boot diff --git a/yudao-ui-admin/src/api/crm/business.js b/yudao-ui-admin/src/api/crm/business.js new file mode 100644 index 000000000..24789df72 --- /dev/null +++ b/yudao-ui-admin/src/api/crm/business.js @@ -0,0 +1,54 @@ +import request from '@/utils/request' + +// 创建商机 +export function createBusiness(data) { + return request({ + url: '/crm/business/create', + method: 'post', + data: data + }) +} + +// 更新商机 +export function updateBusiness(data) { + return request({ + url: '/crm/business/update', + method: 'put', + data: data + }) +} + +// 删除商机 +export function deleteBusiness(id) { + return request({ + url: '/crm/business/delete?id=' + id, + method: 'delete' + }) +} + +// 获得商机 +export function getBusiness(id) { + return request({ + url: '/crm/business/get?id=' + id, + method: 'get' + }) +} + +// 获得商机分页 +export function getBusinessPage(query) { + return request({ + url: '/crm/business/page', + method: 'get', + params: query + }) +} + +// 导出商机 Excel +export function exportBusinessExcel(query) { + return request({ + url: '/crm/business/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} diff --git a/yudao-ui-admin/src/api/crm/businessStatus.js b/yudao-ui-admin/src/api/crm/businessStatus.js new file mode 100644 index 000000000..d4249d7ac --- /dev/null +++ b/yudao-ui-admin/src/api/crm/businessStatus.js @@ -0,0 +1,70 @@ +import request from '@/utils/request' + +// 创建商机状态 +export function createBusinessStatus(data) { + return request({ + url: '/crm/business-status/create', + method: 'post', + data: data + }) +} + +// 更新商机状态 +export function updateBusinessStatus(data) { + return request({ + url: '/crm/business-status/update', + method: 'put', + data: data + }) +} + +// 删除商机状态 +export function deleteBusinessStatus(id) { + return request({ + url: '/crm/business-status/delete?id=' + id, + method: 'delete' + }) +} + +// 获得商机状态 +export function getBusinessStatus(id) { + return request({ + url: '/crm/business-status/get?id=' + id, + method: 'get' + }) +} + +// 获得商机状态分页 +export function getBusinessStatusPage(query) { + return request({ + url: '/crm/business-status/page', + method: 'get', + params: query + }) +} + +// 导出商机状态 Excel +export function exportBusinessStatusExcel(query) { + return request({ + url: '/crm/business-status/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} + +// 根据类型ID获取商机状态信息列表 +export function getBusinessStatusListByTypeId(typeId) { + return request({ + url: '/crm/business-status/get-simple-list?typeId=' + typeId, + method: 'get' + }) +} + +// 获取商机状态信息列表 +export function getBusinessStatusList() { + return request({ + url: '/crm/business-status/get-all-list', + method: 'get' + }) +} diff --git a/yudao-ui-admin/src/api/crm/businessStatusType.js b/yudao-ui-admin/src/api/crm/businessStatusType.js new file mode 100644 index 000000000..5df0aff6c --- /dev/null +++ b/yudao-ui-admin/src/api/crm/businessStatusType.js @@ -0,0 +1,62 @@ +import request from '@/utils/request' + +// 创建商机状态类型 +export function createBusinessStatusType(data) { + return request({ + url: '/crm/business-status-type/create', + method: 'post', + data: data + }) +} + +// 更新商机状态类型 +export function updateBusinessStatusType(data) { + return request({ + url: '/crm/business-status-type/update', + method: 'put', + data: data + }) +} + +// 删除商机状态类型 +export function deleteBusinessStatusType(id) { + return request({ + url: '/crm/business-status-type/delete?id=' + id, + method: 'delete' + }) +} + +// 获得商机状态类型 +export function getBusinessStatusType(id) { + return request({ + url: '/crm/business-status-type/get?id=' + id, + method: 'get' + }) +} + +// 获得商机状态类型分页 +export function getBusinessStatusTypePage(query) { + return request({ + url: '/crm/business-status-type/page', + method: 'get', + params: query + }) +} + +// 导出商机状态类型 Excel +export function exportBusinessStatusTypeExcel(query) { + return request({ + url: '/crm/business-status-type/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} + +// 获取商机状态类型信息列表 +export function getBusinessStatusTypeList() { + return request({ + url: '/crm/business-status-type/get-simple-list', + method: 'get' + }) +} diff --git a/yudao-ui-admin/src/api/crm/contact/contact.js b/yudao-ui-admin/src/api/crm/contact/contact.js new file mode 100644 index 000000000..fd6e0c1ee --- /dev/null +++ b/yudao-ui-admin/src/api/crm/contact/contact.js @@ -0,0 +1,54 @@ +import request from '@/utils/request' + +// 创建crm联系人 +export function createContact(data) { + return request({ + url: '/crm/contact/create', + method: 'post', + data: data + }) +} + +// 更新crm联系人 +export function updateContact(data) { + return request({ + url: '/crm/contact/update', + method: 'put', + data: data + }) +} + +// 删除crm联系人 +export function deleteContact(id) { + return request({ + url: '/crm/contact/delete?id=' + id, + method: 'delete' + }) +} + +// 获得crm联系人 +export function getContact(id) { + return request({ + url: '/crm/contact/get?id=' + id, + method: 'get' + }) +} + +// 获得crm联系人分页 +export function getContactPage(query) { + return request({ + url: '/crm/contact/page', + method: 'get', + params: query + }) +} + +// 导出crm联系人 Excel +export function exportContactExcel(query) { + return request({ + url: '/crm/contact/export-excel', + method: 'get', + params: query, + responseType: 'blob' + }) +} diff --git a/yudao-ui-admin/src/views/crm/business/index.vue b/yudao-ui-admin/src/views/crm/business/index.vue new file mode 100644 index 000000000..b877a33af --- /dev/null +++ b/yudao-ui-admin/src/views/crm/business/index.vue @@ -0,0 +1,335 @@ + + + diff --git a/yudao-ui-admin/src/views/crm/contact/index.vue b/yudao-ui-admin/src/views/crm/contact/index.vue new file mode 100644 index 000000000..acde3615d --- /dev/null +++ b/yudao-ui-admin/src/views/crm/contact/index.vue @@ -0,0 +1,316 @@ + + +